思路:
- 先排序 ;Arrays.sort() 默认升序排序
- 双指针
- left不能放在for循环外,必须要在for循环内,与i相关联,为left = i+1;如果放置在for循环之外,left会出现当left = i 的情况,如例子[-4,-1,0,1,2],当left = i = 1时,right = 4,则 nums[i]+nums[left]+nums[right]=0,那么结果为[-1,-1,2],但是条件数组中-1只有一个。
- 例如当i=0时,whlie(left<right)会将内部在遍历一次,寻找符合条件的组合。
时间复杂度:外层循环+while 相当于两层for循环 O(N*N)
空间复杂度:额外的排序的空间复杂度为 O(logN)
import java.util.*;
class Code15{
public static void main(String[] args) {
int[] nums = {-1,0,1,2,-4};
List<List<Integer>> result = threeSum(nums);
System.out.println(result);
}
public static List<List<Integer>> threeSum(int[] nums) {
// 先排序 后双指针
Arrays.sort(nums);
List<List<Integer>> res = new ArrayList();
int len = nums.length;
for (int i = 0;i < len ;i++ ) {
int left = i+1; // left指针要与i关联,不然会出现同一个数被用2次,即i与left相同时
int right = len - 1;
if(nums[i]>0){//此数大于0,说明后面的和不可能为0
break;
}
if (i>0 && nums[i] == nums[i - 1]) continue; // 不做处理,执行下面,避免重复
while (left < right) { // 会将i=0,1,2,...时,与每一个left right组合
int sum = nums[left] + nums[i] + nums[right];
if (sum == 0) {
res.add(Arrays.asList(nums[left], nums[i], nums[right]));
// 当sum=0时候,移动指针,但是该组合已经添加到结果集中,
// 如果left指针对应不同索引的值相同,不必再添加,所以索引++,继续找下面的组合
if (nums[left] == nums[left + 1]) left++; //避免重复
if (nums[right] == nums[right - 1]) right--;//避免重复
// 当sum=0满足时,将指针移动寻找其他组合
right--;
left++;
} else if (sum > 0) { // 如果sum数大于0,说明要向左移,寻找负数
right--;
} else if (sum < 0) {// 如果sum数小于0,说明要向右移,寻找正数
left++;
}
}
}
return res;
}
}