正确解法:
在排序之后,用for loop确定最小的数,然后让剩下两个指针在最小数的基础上,分列两边,向中间靠拢。
关于重复的考虑:对于最小的指针,只需要保证最小的指针不一样即可。对于另外两个指针,只有在成功塞进结果列的情况下才需要考虑,这时候,只要把重复去掉就好了。
时间复杂度O(n2)。
我的问题:
-
O(n3)次的复杂度:既然我这么用了,其实排序并没有带给我积极的意义。排序本身的作用是利用这一串数字的排列,来减小时间复杂度。
-
对于重复的数字,实际有两个bound来决定要不要继续找数字。
-
有新的数存在
-
在a的基础假设上,以a为动力,来移动指针
→ 用我的方法,存在一个问题,就是当这一串数字的末尾全是重复数字的时候,我无法
预知在后面是否还有新的数字存在。所以,其实从两边向中间的方法就可以解决这个问
题,我只要check左边的指针永远小于右指针就可以了。
修正后的代码:(只作为参考,记录下来)
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> result = new ArrayList<>();
if(nums.length < 3){
return result;
}
Arrays.sort(nums);
if(nums[0] > 0 || nums[nums.length-1] < 0){
return result;
}
for(int i = 0; i < nums.length - 2; i++){
if(i == 0 || nums[i - 1] != nums[i]){
int j = i + 1;
int k = nums.length - 1;
while(j < k){
if(nums[i] == - (nums[j] + nums[k])){
List<Integer> current = new ArrayList<>();
current.add(nums[i]);
current.add(nums[j]);
current.add(nums[k]);
result.add(current);
// check repeated values
while(j < k && nums[j] == nums[j + 1]){
j++;
}
while(j < k && nums[k] == nums[k - 1]){
k--;
}
j++;
k--;
}else if(nums[i] < - (nums[j] + nums[k])){
// nums[j] + nums[k] can be larger
j++;
}else{
k--;
}
}
}
}
return result;
}
}