题目难度:Medium

题目:

Given an array S of n integers, are there elements abc, 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: The solution set must not contain duplicate quadruplets.

翻译:

给定一个n个整数的数组S,在S中是否存在有a、b、c、d的元素使得a+b+c+d=target?如果有,请找出数组中所有唯一的组合。

注意:解决方案集不能包含重复的四胞胎。

【其实和3Sum是一个意思】

思路:既然是在3Sum的基础上加了一个数,那么请允许我可耻的想到了在外面再加。。。。

。。。。。。可是我实在想不到别的了,,外面的循环没有一个标准,所以也不可能在外面再用一遍left与right双重指针。

嗯,那就可耻地写吧

【注意:很多同学面对算法题其实并不是没有思路,而是多多少少有些思路,但是心里知道这个思路很low写了也没多大意思,干脆就不写了而迫不及待去看答案。

这就大错特错了,其实大多数的算法都是由简单算法演变而来的,只是在low算法的基础上或多或少地将冗余的步骤技巧性跳过了。

都不把自己的思路写出来,那么当面对一个从没见过的算法题时思路几乎永远是空白。

况且,平时写简单的计算时各种边界问题的处理也能使我们养成良好的编程习惯和对代码的掌控力。

我们不能为了刷题而刷题,应该是为了锻炼自己的思路。以上个人见解,欢迎讨论】

Code:282 / 282 test cases passed.——72ms(beats 46.27%)    时间复杂度:O(N3)

     public List<List<Integer>> fourSum(int[] nums, int target) {
Arrays.sort(nums);
List<List<Integer>> result = new ArrayList<List<Integer>>(); for (int i = 0; i < nums.length - 3; i++) {
if (i > 0 && nums[i] == nums[i-1]) continue;
for (int j = i + 1; j < nums.length -2; j++) {
if (j > i+1 && nums[j] == nums[j-1]) continue; // 注意j是从i+1开始
int left = j + 1;
int right = nums.length -1;
while (left < right) {
int sum = nums[i] + nums[j] + nums[left] + nums[right]; // 和3sum一个思路 if (sum == target) {
result.add(Arrays.asList(new Integer[]{nums[i], nums[j], nums[left], nums[right]}));
while (left < right && nums[right-1] == nums[right]) right--;
while (left < right && nums[left+1] == nums[left]) left++;
right--;
left++;
} else if (sum > target) {
right--;
} else {
left++;
}
}
}
}
return result;
}

以上直接套用3sum那道题的“双指针法”,然后在外面加了一个for循环,没啥好说的。    3sum:LeetCode第[15]题(Java):3Sum 标签:Array

过程错误:

1.命名错误:length 写成 leng

2.忘记定义类名:直接写成了left = j+1; (left前少写了int)【这就是不建议用(My)Eclipse做算法题的原因,脱离IDE可以改掉很多不好的编码习惯,也对将来面试手写代码帮助不少】

3.忘记写

 else if (nums[left] + nums[right] < sum) {
left++;
} else {
right--;
}

这一部分了,导致最后输出为空,在写if的时候应该把所有的else if 和else都写完,以防止遗漏。这也说明自己还是在凭借对之前用过的算法的记忆在写代码,而没有真正的做到理解后的运用自如,

所以即使自信对某一个算法很熟悉,在写的时候也应该思考它的思想和逻辑,以防止出现关键性的遗漏。

答案1——Cdoe:282 / 282 test cases passed.——29ms(beats 81.40%)    时间复杂度:O(N3)

   public List<List<Integer>> fourSum(int[] nums, int target) {
List<List<Integer>> res=new ArrayList<>();
if(nums.length<4) return res;
Arrays.sort(nums);
for(int i=0;i<nums.length-3;i++){
if(i>0&&nums[i]==nums[i-1]) continue; if(nums[i]*4>target) break;// Too Big!!太大了,后续只能更大,可以直接结束循环;
if(nums[i]+3*nums[nums.length-1]<target) continue;//Too Small!太小了,当前值不需要再算,可以继续循环尝试后面的值。 for(int j=i+1;j<nums.length-2;j++){
if(j>i+1&&nums[j]==nums[j-1]) continue; if(nums[j]*3>target-nums[i]) break;//Too Big! 注意此时不能结束i的循环,因为j是移动的 当j移动到后面的时候继续i循环也sum可能变小
if(nums[j]+2*nums[nums.length-1]<target-nums[i]) continue;// Too Small int begin=j+1;
int end=nums.length-1;
while(begin<end){
int sum=nums[i]+nums[j]+nums[begin]+nums[end];
if(sum==target){
res.add(Arrays.asList(nums[i],nums[j],nums[begin],nums[end]));
while(begin<end && nums[begin]==nums[begin+1]){begin++;}
while(begin<end && nums[end]==nums[end-1]){end--;}
begin++;
end--;
}else if (sum<target){
begin++;
}else{
end--;
}
}
}
}
return res;
}

和我的解法是一样的,但是多加了一些条件判断,去除了一些重复数据和过大过小数据:

当前起点 i,肯定是此后数组中能组合的四个数中最小的,4*nums[i] 都大于target的话那么说明此后数组中任何组合都会比target大,此时可以直接结束当前循环。【j循环同理】

      如果nums[i] + 3nums[len-1]肯定是不会比后续任何组合小的,如果这个都小于target,那么说明以nums[i]开头的后续任何组合都会比target小,此时可以进入下一层循环。【j循环同理】

这样在很多测试用例时能省下不少时间。

面试手写的时候大家可以秀一秀这样的操作,但是做公司的笔试题的时候因为做题时间有限,除非已经都AC,否则优先保证完整性即可。

这波强行解释怎么样!

答案2——Code:282 / 282 test cases passed.——28ms(beats 83.45%)    时间复杂度:O(N3)

     public List<List<Integer>> fourSum(int[] nums, int target) {
ArrayList<List<Integer>> res = new ArrayList<List<Integer>>();
int len = nums.length;
if (nums == null || len < 4)
return res; Arrays.sort(nums); int max = nums[len - 1];
if (4 * nums[0] > target || 4 * max < target)
return res; int i, z;
for (i = 0; i < len; i++) {
z = nums[i];
if (i > 0 && z == nums[i - 1])// avoid duplicate
continue;
if (z + 3 * max < target) // z is too small
continue;
if (4 * z > target) // z is too large
break;
if (4 * z == target) { // z is the boundary
if (i + 3 < len && nums[i + 3] == z)
res.add(Arrays.asList(z, z, z, z));
break;
} threeSumForFourSum(nums, target - z, i + 1, len - 1, res, z);
} return res;
} /*
* Find all possible distinguished three numbers adding up to the target
* in sorted array nums[] between indices low and high. If there are,
* add all of them into the ArrayList fourSumList, using
* fourSumList.add(Arrays.asList(z1, the three numbers))
*/
public void threeSumForFourSum(int[] nums, int target, int low, int high, ArrayList<List<Integer>> fourSumList,
int z1) {
if (low + 1 >= high)
return; int max = nums[high];
if (3 * nums[low] > target || 3 * max < target)
return; int i, z;
for (i = low; i < high - 1; i++) {
z = nums[i];
if (i > low && z == nums[i - 1]) // avoid duplicate
continue;
if (z + 2 * max < target) // z is too small
continue; if (3 * z > target) // z is too large
break; if (3 * z == target) { // z is the boundary
if (i + 1 < high && nums[i + 2] == z)
fourSumList.add(Arrays.asList(z1, z, z, z));
break;
} twoSumForFourSum(nums, target - z, i + 1, high, fourSumList, z1, z);
} } /*
* Find all possible distinguished two numbers adding up to the target
* in sorted array nums[] between indices low and high. If there are,
* add all of them into the ArrayList fourSumList, using
* fourSumList.add(Arrays.asList(z1, z2, the two numbers))
*/
public void twoSumForFourSum(int[] nums, int target, int low, int high, ArrayList<List<Integer>> fourSumList,
int z1, int z2) { if (low >= high)
return; if (2 * nums[low] > target || 2 * nums[high] < target)
return; int i = low, j = high, sum, x;
while (i < j) {
sum = nums[i] + nums[j];
if (sum == target) {
fourSumList.add(Arrays.asList(z1, z2, nums[i], nums[j])); x = nums[i];
while (++i < j && x == nums[i]) // avoid duplicate
;
x = nums[j];
while (i < --j && x == nums[j]) // avoid duplicate
;
}
if (sum < target)
i++;
if (sum > target)
j--;
}
return;
}

呃,还写了两个调用函数。。,

它在主函数里面循环调用了3sum的算法,然后加了一些判断,其实就是和答案1一样的也就是和我的也是一样的。。。。。。

LeetCode第[18]题(Java):4Sum 标签:Array的更多相关文章

  1. LeetCode第[1]题(Java):Two Sum 标签:Array

    题目: Given an array of integers, return indices of the two numbers such that they add up to a specifi ...

  2. LeetCode第[1]题(Java):Two Sum (俩数和为目标数的下标)——EASY

    题目: Given an array of integers, return indices of the two numbers such that they add up to a specifi ...

  3. LeetCode第[46]题(Java):Permutations(求所有全排列) 含扩展——第[47]题Permutations 2

    题目:求所有全排列 难度:Medium 题目内容: Given a collection of distinct integers, return all possible permutations. ...

  4. LeetCode第[15]题(Java):3Sum 标签:Array

    题目难度:Medium 题目: Given an array S of n integers, are there elements a, b, c in S such that a + b + c  ...

  5. LeetCode第[16]题(Java):3Sum Closest 标签:Array

    题目难度:Medium 题目: Given an array S of n integers, find three integers in S such that the sum is closes ...

  6. LeetCode第[4]题(Java):Median of Two Sorted Arrays 标签:Array

    题目难度:hard There are two sorted arrays nums1 and nums2 of size m and n respectively. Find the median ...

  7. LeetCode第[26]题(Java):Remove Duplicates from Sorted Array 标签:Array

    题目难度:Easy 题目: Given a sorted array, remove the duplicates in-place such that each element appear onl ...

  8. LeetCode第[11]题(Java):Container With Most Water 标签:Array

    题目难度:Medium Given n non-negative integers a1, a2, ..., an, where each represents a point at coordina ...

  9. LeetCode第[88]题(Java):Merge Sorted Array(合并已排序数组)

    题目:合并已排序数组 难度:Easy 题目内容: Given two sorted integer arrays nums1 and nums2, merge nums2 into nums1 as ...

随机推荐

  1. hdu 5078 Osu! (2014 acm 亚洲区域赛鞍山 I)

    题目链接:http://acm.hdu.edu.cn/showproblem.php? pid=5078 Osu! Time Limit: 2000/1000 MS (Java/Others)     ...

  2. break and continue

    public class HelloWorld { public static void main(String[] args) { int sum = 0; for (int i = 1; i &l ...

  3. 十一、Spring Boot 集成Shiro和CAS

    1.Shiro 是什么?怎么用? 2.Cas 是什么?怎么用? 3.最好有spring基础 首先看一下下面这张图: 第一个流程是单纯使用Shiro的流程. 第二个流程是单纯使用Cas的流程. 第三个图 ...

  4. IDEA 初始配置教程

    IDEA 初始配置教程 如果你是第一次使用 IDEA,或者对 IDEA 常用配置仍然不熟悉,那么本文就特别适合你. 本文只是根据我自己的使用经验来进行配置,不一定适合所有的情况,但是对你肯定会有帮助. ...

  5. 工作随笔——spring异步处理@Async使用笔记

    @Async使用笔记 必须是public方法 必须是非static方法 方法调用的实例必须由spring创建和管理 代码示例如下: // 创建Foo类@Component class Foo { @A ...

  6. 《程序设计语言——实践之路》【PDF】下载

    程序设计语言--实践之路>[PDF]下载链接: https://u253469.pipipan.com/fs/253469-230382240 内容简介 本书在美国大学已有使用了十余年,目前被欧 ...

  7. 如何优雅地在React项目中使用Redux

    前言 或许你当前的项目还没有到应用Redux的程度,但提前了解一下也没有坏处,本文不会安利大家使用Redux 概念 首先我们会用到哪些框架和工具呢? React UI框架 Redux 状态管理工具,与 ...

  8. 【python】字典dict

  9. bzoj 4013: [HNOI2015]实验比较

    Description 小D 被邀请到实验室,做一个跟图片质量评价相关的主观实验.实验用到的图片集一共有 N 张图片,编号为 1 到 N.实验分若干轮进行,在每轮实验中,小 D会被要求观看某两张随机选 ...

  10. 虚拟机创建流程中neutron代码分析(三)

    前言: 当neutron-server创建了port信息,将port信息写入数据库中.流程返回到nova服务端,接着nova创建的流程继续走.在计算节点中neutron-agent同样要完成很多的工作 ...