Given an array S of n integers, are there elements a, b, c, and d in S such that a + b + c + d = target? Find all unique quadruplets in the array which gives the sum of target.
Note:
Elements in a quadruplet (a,b,c,d) must be in non-descending order. (ie, a ≤ b ≤ c ≤ d)
The solution set must not contain duplicate quadruplets.
For example, given array S = {1 0 -1 0 -2 2}, and target = 0.
A solution set is:
(-1, 0, 0, 1)
(-2, -1, 1, 2)
(-2, 0, 0, 2)
蛮有意思的一道题目。
在做了前面几道2sum,3sum之后,形成了思维定势,用四个for循环来暴力处理,结果出现了超时。百思不得其解之后,看了网上的一个思路:
因为已经排序了,所以sum=num[index1]+num[index2]+num[index3]+num[left]
就是在index1,index2已经有的基础上,index3放在左边,left(剩下的)放在右边,
index1 | index2 | ... | index3-> | ... | ... | ... | ... | ... | <-left |
如果sum>target,则说明应该左移left。
因为index3只能右移并且右移会造成sum>target。
如果sum<target,则右移index3。
题目要求不能出现重复的解,但是num数组中会有重复的元素,所以对重复解的判定位置要定位好,就是哪里移动在哪里判定。
一开始left的判定我放在了index3判定的后面,结果会导致一种情况就是left相同,并且是解,那么因为left相同的判定会导致这个解被提前给continue掉。
整道题目还是蛮有意思的,特别是O(N^3)来替换掉O(N^2)这个思路特别有意思。
上代码
public class Solution {
public List<List<Integer>> fourSum(int[] num, int target) {
List<List<Integer>> rstList = new ArrayList<List<Integer>>();
if(num.length<4)return rstList;
Arrays.sort(num);
for (int index1 = 0; index1 < num.length; ++index1) {
if (index1 != 0 && num[index1] == num[index1 - 1])
continue;
for (int index2 = index1 + 1; index2 < num.length; ++index2) {
if (index2 != index1 + 1 && num[index2] == num[index2 - 1])
continue;
int left=num.length-1;
for (int index3 = index2 + 1;left>index3&& index3 < num.length; ++index3) {
//if(left<=index3)break;
if (index3 != index2 + 1
&& num[index3] == num[index3 - 1])
continue;
//if (left != num.length - 1&& num[left] == num[left + 1])continue;left相同不应该放在这边处理,而且处理的方式也不对
int tmp=num[index1]+num[index2]+num[index3]+num[left];
if(tmp==target){
List<Integer> tmpList=new ArrayList<>();
tmpList.add(num[index1]);
tmpList.add(num[index2]);
tmpList.add(num[index3]);
tmpList.add(num[left]);
rstList.add(tmpList);
}else{//重点
if(tmp>target){left--;
if(left!=num.length-1&&num[left+1]
==num[left])left--;//left相同应放在这边处理
//if(left<=index3)break;
index3--;
}//尝试左移left,并且保持index3不变来看看是否有合适的
}
}
}
}
return rstList;
}
}