问题:

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: 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]

]

官方难度:

Medium

翻译:

给定一个长度为n的无序数组S和目标数字target,在数组S中找出4个整数a,b,c,d,使a+b+c+d=target。

找出所有的可能解,且解集中不包含重复项。

例子:

数组S:{ 1, 0, -1, 0, -2, 2},目标值target=0。

解集为[ [-1,0,0,1],[-2,-1,1,2],[-2,0,0,2] ]。

  1. 显然,本题是No.001(Two Sum),No.015(3Sum),No.016(3Sum Closest)更深一步的讨论。在解决这道问题时,不妨考虑一种解法,适用于5Sum,6Sum之后一系列的问题。我可以将这些问题总结归纳为:kSum问题,k>=2。
  2. 显然是需要使用递归,而递归的终点就是2Sum问题。
  3. 将递归方法独立出来,在进入递归之前,优先给数组排序(如k=2,这种做法会略微影响性能)。
  4. 2Sum问题,仍然使用夹逼的原则,同时维护两侧的previous值。增加优化策略:当前左值大于目标数且当前左值大于0,return;当2倍前左值大于目标值,或2倍当前右值小于目标值,return。
  5. 当k>2时,做类似2Sum的优化策略,将当前目标值-当前值,作为递归入参的目标值,同时传入当前索引值,进行递归。
  6. 获得递归的解集,循环加入当前值到解集中返回。
  7. 注意入参检查。

解题代码:

     public static List<List<Integer>> fourSum(int[] nums, int target) {
if (nums == null || nums.length < 4) {
throw new IllegalArgumentException("Input error");
}
Arrays.sort(nums);
return kSum(nums, 0, target, 4);
} private static List<List<Integer>> kSum(int[] nums, int startIndex, int target, int kSum) {
List<List<Integer>> result = new LinkedList<>();
// 递归终点是2Sum问题
if (kSum == 2) {
int left = startIndex, right = nums.length - 1;
int preLeft = Integer.MIN_VALUE, preRight = Integer.MIN_VALUE;
while (left < right) {
if (nums[left] > target && nums[left] > 0) {
return result;
}
if (2 * nums[left] > target || 2 * nums[right] < target) {
return result;
}
if (nums[left] == preLeft) {
left++;
continue;
}
if (nums[right] == preRight) {
right--;
continue;
}
int sum = nums[left] + nums[right];
if (sum == target) {
List<Integer> list = new LinkedList<>();
list.add(nums[left]);
list.add(nums[right]);
result.add(list);
}
if (sum < target) {
preLeft = nums[left];
left++;
} else {
preRight = nums[right];
right--;
}
}
} else {
// 大于2Sum问题,使用递归
int previous = Integer.MAX_VALUE;
for (int i = startIndex; i < nums.length - 1; i++) {
if (nums[i] > target && nums[i] > 0) {
return result;
}
// target值的范围超过k个极值
if (kSum * nums[i] > target || kSum * nums[nums.length - 1] < target) {
return result;
}
if (nums[i] == previous) {
continue;
}
int tempTarget = target - nums[i];
// 开启递归
List<List<Integer>> tempResult = kSum(nums, i + 1, tempTarget, kSum - 1);
for (List<Integer> a : tempResult) {
a.add(nums[i]);
result.add(a);
}
previous = nums[i];
}
}
return result;
}

fourSum

相关链接:

https://leetcode.com/problems/4sum/

https://github.com/Gerrard-Feng/LeetCode/blob/master/LeetCode/src/com/gerrard/algorithm/medium/Q018.java

PS:如有不正确或提高效率的方法,欢迎留言,谢谢!

No.018:4Sum的更多相关文章

  1. Python练习题 018:打印星号菱形

    [Python练习题 018] 打印出如下图案(菱形): * *** ***** ******* ***** *** * --------------------------------------- ...

  2. LeetCode第[18]题(Java):4Sum 标签:Array

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

  3. C++笔记018:构造函数的调用规则

      原创笔记,转载请注明出处! 点击[关注],关注也是一种美德~ 一.默认构造函数 两个特殊的构造函数 1.默认无参构造函数 当类中没有定义构造函数时,编译器默认提供一个无参构造函数,并且其函数体为空 ...

  4. Python3练习题 018:打印星号菱形

    Python的内置方法 str.center(width [, fillchar]) 就能轻而易举打印出来:str即是数量不等的星号,width即是最大宽度(7个空格),默认填充字符fillchar就 ...

  5. 018:InnoDB 存储引擎、表空间

    目录 一.InnoDB 存储引擎 1. InnoDB的历史 2. InnoDB的特点 3. InnoDB存储引擎的文件 3.1 概述 3.2 InnoDB - 表空间 3.3 General表空间 3 ...

  6. LeetCode OJ:4Sum(4数字之和)

    Given an array S of n integers, are there elements a, b, c, and d in S such that a + b + c + d = tar ...

  7. 018:include函数详解

    include函数详解(了解——虽然用的很少): include函数的用法,目前有三种使用方式: 1.include(module,namespace=None): module:子url的模块字符串 ...

  8. LeetCode18:4Sum

    Given an array S of n integers, are there elements a, b, c, and d in S such that a + b + c + d = tar ...

  9. ELK学习实验018:filebeat收集docker日志

    Filebeat收集Docker日志 1 安装docker [root@node4 ~]# yum install -y yum-utils device-mapper-persistent-data ...

随机推荐

  1. Struts2常量的具体用法实例

    <!-- 指定Web应用的默认编码集,相当于调用HttpServletRequest的setCharacterEncoding方法 --> <constant name=" ...

  2. 更新日志 - fir.im Jenkins & Gradle 插件上线

    最近 fir.im 工程师们效率爆表,fir.im 实用工具集合又添加了新的成员-- Jenkins & Gradle 插件,让 App 打包上传更加简单快速. fir.im Jenkins ...

  3. html5 响应式布局

    一.什么是响应式布局?       响应式布局是Ethan Marcotte在2010年5月份提出的一个概念,简而言之,就是一个网站能够兼容多个终端——而不是为每个终端做一个特定的版本. 这个概念是为 ...

  4. react7 react 三目运算

    <body><!-- React 真实 DOM 将会插入到这里 --><div id="example"></div> <!- ...

  5. 每天一个linux命令(44):top命令

    top命令是Linux下常用的性能分析工具,能够实时显示系统中各个进程的资源占用状况,类似于Windows的任务管理器.下面详细介绍它的使用方法.top是一个动态显示过程,即可以通过用户按键来不断刷新 ...

  6. 快速入门系列--MVC--03控制器和IOC应用

    Asp.net MVC也接触好久了,但由于自己一直主要负责后台,尤其是数据库方面的工作对于该框架并没有一个很好的了解,尤其是蒋金楠大师的ASP.NET MVC4框架剖析一书都买了2年多了,真正认真看过 ...

  7. iOS设备的越狱方法

    最近公司的事情很忙,在开发一个类似于微信的App,经常加班,所以也没有时间去更新微信公众账号的内容了.iOSJailbreak, 申请这个账号大概有一个多月了吧,发布的内容不多,更多是针对开发者的内容 ...

  8. PHP的学习--图解PHP引用

    在一篇文章中看到关于PHP引用的图解,对于加深对PHP引用的理解很有帮助,在这里备份一下. 如果你对PHP的引用一点也不了解,可以先看我之前的博客:PHP的学习--PHP的引用

  9. 深入浅出JSONP--解决ajax跨域问题

    取不到数据! 上周客户新买了服务器,原本在旧的服务器上放着客户的Web主页信息和一个后台程序(asp.net),在客户的主页中有一个动态显示最新消息的处理,这个处理就是通过ajax异步从那个后台程序中 ...

  10. CSS 魔法系列:纯 CSS 绘制各种图形《系列五》

    我们的网页因为 CSS 而呈现千变万化的风格.这一看似简单的样式语言在使用中非常灵活,只要你发挥创意就能实现很多比人想象不到的效果.特别是随着 CSS3 的广泛使用,更多新奇的 CSS 作品涌现出来. ...