leecode双指针部分题目
- 1. 验证回文串
- 2. 判断子序列
- 3. 两数之和 II - 输入有序数组
- 4. 盛最多水的容器
- 5. 三数之和
1. 验证回文串
如果在将所有大写字符转换为小写字符、并移除所有非字母数字字符之后,短语正着读和反着读都一样。则可以认为该短语是一个 回文串 。
字母和数字都属于字母数字字符。
给你一个字符串 s,如果它是 回文串 ,返回 true ;否则,返回 false 。
解题思路: 遍历字符串,判断是否为字母或数字,使用Character.isLetterOrDigit(),如果是则放入StringBuilder中。
保存一个原本的字符串和反转后的字符串,判断是否相同。
class Solution {public boolean isPalindrome(String s) {StringBuilder re = new StringBuilder();// 过滤字符并标准化为小写for (char c : s.toCharArray()) {if (Character.isLetterOrDigit(c)) { // 只考虑字母和数字re.append(Character.toLowerCase(c)); // 转为小写并添加到 StringBuilder}}// 保存过滤后的字符串String filteredString = re.toString(); // 不翻转// 生成逆置字符串String rev = re.reverse().toString(); // 反转System.out.println("Filtered String: " + filteredString);System.out.println("Reversed String: " + rev);// 比较原始过滤的字符串和反转字符串是否相等return filteredString.equals(rev);
}
}
2. 判断子序列
给定字符串 s 和 t ,判断 s 是否为 t 的子序列。
字符串的一个子序列是原始字符串删除一些(也可以不删除)字符而不改变剩余字符相对位置形成的新字符串。(例如,"ace"是"abcde"的一个子序列,而"aec"不是)。
解题思路: 同时遍历这两个字符串,如果相等则i++,j++,如果不相等则只让i++,最后返回i是否超过它本身长度,如果超过则true,如果没有则false。
class Solution {public boolean isSubsequence(String s, String t) {int i = 0;int j = 0;char[] ss = s.toCharArray();char[] ts = t. toCharArray();while(i < ss.length && j < ts.length){if(ss[i] != ts[j]){j++;}else{i++;j++;}}return i == ss.length ;}
}
3. 两数之和 II - 输入有序数组
给你一个下标从 1 开始的整数数组 numbers ,该数组已按 非递减顺序排列 ,请你从数组中找出满足相加之和等于目标数 target 的两个数。如果设这两个数分别是 numbers[index1] 和 numbers[index2] ,则 1 <= index1 < index2 <= numbers.length 。
以长度为 2 的整数数组 [index1, index2] 的形式返回这两个整数的下标 index1 和 index2。
你可以假设每个输入 只对应唯一的答案 ,而且你 不可以 重复使用相同的元素。
你所设计的解决方案必须只使用常量级的额外空间。
解题思路: 使用和二分查找相似的思路,设置low等于0,high等于len-1,只要low <high,则让sum = num[low] + num [high],如果sum<target,则说明需要low++,如果大于则说明需要high–,如果相等则返回索引值加一,如果都遍历完都没找到结果则直接返回【-1,-1】
class Solution {public int[] twoSum(int[] numbers, int target) {int low = 0, high = numbers.length - 1;while (low < high) {int sum = numbers[low] + numbers[high];if (sum == target) {return new int[]{low + 1, high + 1};} else if (sum < target) {++low;} else {--high;}}return new int[]{-1, -1};}
}
4. 盛最多水的容器
给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。
找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
返回容器可以储存的最大水量。
说明:你不能倾斜容器。
解题思路: 设置l 和 r,一个在最左边,一个在最右边,只要l<r,则执行,首先计算面积area = min(l,r) * (r - l), 用 ans = max(ans,area),如果l的高度小于等于r的高度,则l++,如果大于则r–,以此找出最大面积。
public class Solution {public int maxArea(int[] height) {int l = 0, r = height.length - 1;int ans = 0;while (l < r) {int area = Math.min(height[l], height[r]) * (r - l);ans = Math.max(ans, area);if (height[l] <= height[r]) {++l;}else {--r;}}return ans;}
}
5. 三数之和
给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请你返回所有和为 0 且不重复的三元组。
解题思路: 首先数组排序,用i遍历数组,L = i+1,R= len - 1,如果num[i]大于0,则说明最小的大于0,直接返回,如果num[i] == num[i+1] 则继续执行,去重。
再循环内使用双指针,只要L<R,就执行,让sum = num[i] + num[L] + num[R],如果等于0,则把这三个数放入列表中存下,给L和R去重,让L和R取到新值。
如果sum>0,则R–;
如果sum<0,则L++;
如此遍历得到最终答案。
class Solution {public List<List<Integer>> threeSum(int[] nums) {List<List<Integer>> res = new ArrayList<List<Integer>>();int len = nums.length;if(len < 3 || nums == null) return res;Arrays.sort(nums);for(int i = 0; i < len; i++){int L = i + 1;int R = len - 1;if(nums[i] > 0) break;if(i>0 && nums[i] == nums[i-1]){continue;}while(L < R){int sum = nums[i] + nums[L] + nums[R];if(sum == 0){res.add(Arrays.asList(nums[i],nums[L],nums[R]));while(L<R&&nums[L] == nums[L+1]) L++;while(L<R && nums[R] == nums[R-1]) R--;L++;R--;}else if(sum > 0) R--;else if(sum < 0) L++;} }return res;
}}