这道题是扩展的三数之和。在三数之和中,我们固定a,利用双指针寻找b和c(两头分别开始找),将复杂度从3次方降到了2次方。在四数之和中,我们固定a和b,双指针寻找c和d。将复杂度从4次方降到了3次方。
1.考虑剪枝情况。如果nums[a]比目标和值大,就一定不可能找到结果吗?如nums[a]是正数,它作为四元组中最小的数都大于结果,那么必定找不到结果了。如果是nums[a]是负数,它大于目标和target(也是一个负数),还可能出现大于nums[a]的负数,比如nums[b]负数,nums[a]+nums[b]会变得更小,是一个更小的负数,还是有可能找到结果的。
2.考虑整数溢出情况,使用long。Java中int类型的最小值是-2147483648,最大值是2147483647。在这个样例中,和可能越界了。
java">class Solution {public List<List<Integer>> fourSum(int[] nums, int target) {Arrays.sort(nums);int len=nums.length;ArrayList<List<Integer>> res=new ArrayList<>();for(int a=0;a<len-3;a++){//剪枝:正数最小的数a都大于目标了,肯定没结果。如果是大于目标的负数a,负数a+负数b还是可能小于目标的。if(nums[a]>target&&nums[a]>=0){break;}if(a-1>=0&&nums[a-1]==nums[a]){//去重acontinue;}for(int b=a+1;b<len-2;b++){//剪枝:if(nums[a]+nums[b]>target&&nums[a]+nums[b]>=0){break;}if(b-1>a&&nums[b-1]==nums[b]){//去重bcontinue;}long t=target-(long)(nums[a]+nums[b]);//新的寻找目标int c=b+1,d=len-1;while(c<len&&d>b&&c<d){if(t>(long)nums[len-1]+nums[len-2]){break;}if((long)nums[c]+nums[d]==t){ArrayList<Integer> list=new ArrayList<>();list.add(nums[a]);list.add(nums[b]);list.add(nums[c]);list.add(nums[d]);res.add(list);while(c<d&&nums[c+1]==nums[c]){//去重cc++;}while(c<d&&nums[d-1]==nums[d]){//去重d d--;}c++;d--; }else if((long)nums[c]+nums[d]>t){d--;}else{c++;}}}}return res;}
}