题目
结果
代码如下:
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
Arrays.sort(nums);
List<List<Integer>> outter = new ArrayList<>();
int length = nums.length;
int end = length-1;
int stop = length-2;
for(int i =0 ;i < stop;i++ ){
if(i>0&&nums[i]==nums[i-1]){
continue;
}
List<Integer> inner = new ArrayList<>(3);
int target = -nums[i];
int leftIndex = i+1;
int rightIndex = end;
int left = nums[leftIndex];
int right = nums[rightIndex];
while(leftIndex<rightIndex){
left = nums[leftIndex];
right = nums[rightIndex];
int all = left + right;
if(all > target){
while(leftIndex<rightIndex&&nums[rightIndex]==nums[rightIndex-1]){
--rightIndex;
}
--rightIndex;
}else if(all < target){
while(leftIndex<rightIndex&&nums[leftIndex]==nums[leftIndex+1]){
leftIndex++;
}
++leftIndex;
}else{
inner.add(-target);
inner.add(left);
inner.add(right);
outter.add(inner);
inner = new ArrayList<>(3);
while(leftIndex<rightIndex&&nums[rightIndex]==nums[rightIndex-1]){
--rightIndex;
}
--rightIndex;
while(leftIndex<rightIndex&&nums[leftIndex]==nums[leftIndex+1]){
++leftIndex;
}
++leftIndex;
}
}
}
return outter;
}
}
思路
这道题一开始除了暴力三重循环还真没有思路,看了题解才想到这种做法,具体而言,就是先排序,这样数组就是从小到大的了。每次按照顺序选择一个元素nums[i]
,假设他为最小的元素,然后指定两个指针(指针碰撞),左指针为i+1
,右指针为数组length-1
,这样判断左指针与右指针的和与-1*nums[i]
的大小比较,如果小于,那么证明左右的和小了,那么左指针右移一个(注意如果右移的一个与原来的一样,那么还需要右移,直到不一样或者左右交汇——左右交汇就代表没有可用的元素了,对于nums[i]
的判断结束,要进入下一个nums[i]
了,因为结果要3个元素,左右交汇即使与nums[i]
的和为0,那么也只能有2个元素了),反之,如果大于,则右指针左移一个,移动的注意事项与做指针相同。知道左右指针碰撞在一起,证明对于nums[i]
没有合适的元素了,就需要找下一个nums[i]
了。