15. 3Sum
Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0?
Find all unique triplets in the array which gives the sum of zero.
Note: The solution set must not contain duplicate triplets.
For example, given array S = [-1, 0, 1, 2, -1, -4],
A solution set is:
[
[-1, 0, 1],
[-1, -1, 2]
]
想起了前面的2 Sum那个题,查了下才发现原来k Sum是一种类型的题。。
突然想起来前几天做的网易内推笔试中有一道K Sum原理的题。果然经验需要积累呀。
首先肯定不能用暴力的解法了,三层fof循环,时间复杂度O(n^3)肯定时间超过限制。
思路是:先对数组进行排序,排序后用两个指针分别从数组的前后两端向中间扫描,可以先固定一个数,
然后找另外两个数之和与固定的数相加为指定的目标数,这个题该target是0。
public class Solution {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> list = new ArrayList<List<Integer>>();
if (nums == null || nums.length<3) {
return list;
}
Arrays.sort(nums);
for (int i = 0; i < nums.length-2; i++) {//nums.length-2的目的是最后一个数不用在计算了,前面的计算已经包括了最后一个数的情况
if (i>0 && nums[i]==nums[i-1]) continue; //从i=0开始判断,若i=1....以后和前面的数使重复的,则继续判断直到不同为止
int begin = i+1;//从i+1开始查找出两个数和nums[i]相加等于0
int end = nums.length-1;
//
while (begin < end) {
if (nums[begin]+nums[end]+nums[i] == 0) {
List<Integer> res = new ArrayList<Integer>();
res.add(nums[i]);
res.add(nums[begin]);
res.add(nums[end]);
list.add(res);//存入到结果集中
//下面的两个while,可以避免结果集中有重复,因为数组时排好序的,
//所以当一个数被放到结果集中的时候,其后面和它相等的直接被跳过。
//右移的时候如果相等就继续右移
while (begin < end && nums[begin] == nums[begin+1]) {
begin++;
}
//左移的时候如果相等就继续左移
while (begin < end && nums[end] == nums[end-1]) {
end--;
}
begin++;
end--;
}else if (nums[begin]+nums[end]+nums[i] < 0) {
begin++;
}else {
end--;
}
}
}
return list;
}
}
注意,对于 num[i],寻找另外两个数时,只要从 i+1 开始找就可以了。