一 题目
Given an array nums
of n integers, are there elements a, b, c in nums
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.
Example:
Given array nums = [-1, 0, 1, 2, -1, -4], A solution set is: [ [-1, 0, 1], [-1, -1, 2] ]
二 分析
本题是medium 级别。求数组里面三数之和为0的组合。
除了暴力循环外O(n^3),有个滑动窗口的降维思路,大致思想就是先取出一个数,再求两数的sum看看是否满足?
具体实现就是先排序,在滑动。基准点为a=nums[i], b= nums[left],c = nums[right]
其中初始化 left = i+1,right= nums.length-1;
分情况判断,如果符合条件,则加入结果,right向左滑动,如果《0,则left向右滑动,如果》0则right向左滑动。也就是滑动窗口往中间滑的问题。自己写的时候,还要注意一点,重复项的问题,我只是简单的结果过滤了。
代码如下:
public static void main(String[] args) {
int[] nums1 = {0,0,0};
List<List<Integer>> res1 = threeSum(nums1);
System.out.println(res1 );
int[] nums = {-1, 0, 1, 2, -1, -4};
List<List<Integer>> res = threeSum(nums);
System.out.println(res );
}
public static List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> reslist = new ArrayList<List<Integer>>();
if(nums== null){
return null;
}
//先排序
Arrays.sort(nums);
for(int i=0;i<= nums.length-3;i++){
int left = i+1;
int right = nums.length-1;
while(left< right){
if(nums[i]+nums[left]+nums[right]==0){
List<Integer> tlist = Arrays.asList(nums[i],nums[left],nums[right]);
if(!reslist.contains(tlist)){
reslist.add(tlist);
}
right --;
}
else if(nums[i]+nums[left]+nums[right]>0){
right --;
}else if(nums[i]+nums[left]+nums[right]<0){
left++;
}
}
}
return reslist;
}
Runtime: 875 ms, faster than 5.00% of Java online submissions for 3Sum.
Memory Usage: 55.1 MB, less than 5.29% of Java online submissions for3Sum.
太慢了,这是O(n^2) 吧。怎么才能提高速度呢?
网上看了大神的文章。思路还是这个思路,但是判断重复使用了指针判断相邻元素,而不是使用结果集list的判重 。
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> reslist = new ArrayList<List<Integer>>();
if (nums.length < 3) return reslist;
//先排序
Arrays.sort(nums);
for(int i=0;i<= nums.length-3;i++){
if (i > 0 && nums[i] == nums[i - 1]) continue; // skip duplicates
int left = i+1;
int right = nums.length-1;
while(left< right){
if(nums[i]+nums[left]+nums[right]==0){
reslist.add(Arrays.asList(nums[i],nums[left],nums[right]));
while (++left < right && nums[left-1] == nums[left]) {}; // skip duplicates
while (--right>left && nums[right+1] == nums[right]) {}; // skip duplicates
}
else if(nums[i]+nums[left]+nums[right]>0){
right --;
}else {
left++;
}
}
}
return reslist;
}
Runtime: 30 ms, faster than 83.78% of Java online submissions for 3Sum.
Memory Usage: 48.2 MB, less than 81.62% of Java online submissions for3Sum.
看似不大的改动,却极大提升了效率。666.
更多详情,参见:https://zhuanlan.zhihu.com/p/24681450