前言
针对数组,双指针可能会有更低的时空复杂度,甚至是解题关键,对于两数之和、三数之和,它们逻辑是一样的,即将三数向右一项一位。
一、案例
1、两数之和
2、三数之和
二、题解
1、两数
前后双指针,快速找到两数之和。
public int[] twoSum(int[] numbers, int target) {
//前后双指针
int begin = 0, end = numbers.length - 1;
while (begin < end) {
int res = numbers[begin] + numbers[end];
if (res < target) begin++;
else if (res > target) end--;
else return new int[]{begin, end};
}
return null;
}
3、三数
先排序,然后从最小值开始固定并在固定处切分数组,再在右段数组开始双指针,同时注意通过前后是否相等来进行去重。
package com.xhu.offer.offerII;
import java.util.*;
//数组中和为0的三个数
public class ThreeSum {
//总结,按照以前的方式,理清思路是关键,理不清就之间题解,然后自己在沉淀自己所理解的。
public List<List<Integer>> threeSum(int[] nums) {
//先排序,固定一个数,然后双指针开始找满足条件的值。
List<List<Integer>> res = new ArrayList<>();
if (nums.length < 3) return res;
Arrays.sort(nums);
int pre1 = Integer.MAX_VALUE;
for (int i = 0; i < nums.length - 2; i++) {
if (pre1 == nums[i]) continue;
pre1 = nums[i];
int begin = i + 1, end = nums.length - 1;
List<Integer> el = new ArrayList<>();
int pre2 = Integer.MAX_VALUE,pre3 = pre2;
while (begin < end) {
boolean flag = pre2 == nums[begin];
boolean flag2 = pre3 == nums[end];
begin += flag ? 1 : 0;
end -= flag2 ? 1 : 0;
if (flag || flag2) continue;
int temp = nums[begin] + nums[end];
if (temp < -nums[i]) pre2 = nums[begin++];
else if (temp > -nums[i]) pre3 = nums[end--];
else {
pre2 = nums[begin];
pre3 = nums[end];
el.add(nums[i]);
el.add(nums[begin++]);
el.add(nums[end--]);
res.add(el);
el = new ArrayList<>();
}
}
}
return res;
}
}
总结
1)按照以前的方式,理清思路是关键,理不清就之间题解,然后自己在沉淀自己所理解的。
参考文献
[1] LeetCode 两数之和
[2] LeetCode 三数之和