Leetcode #18 4Sum 四数之和 解题小节+K-Sum思想
2016-03-20 20:15
441 查看
1题目理解
Leetcode不少题目是成一个体系的,这道题是找四数之和等于四数之和的题,之前还有2Sum和3Sum,我也已经做了题目的小节,可以点开进行查看。Leetcode #15 3Sum 三数之和 解题小节
Leetcode #1 Two Sum 解题小结
和之前的问题一样,有如下的限制:
1、最终输出的顺序是非降序的(所以我们首先需要排序)
2、不能输出重复的解(所以我们要注意移动)
这道题的解法,从最终的运行时间,我提供的解法应该属于次优级的,也就是说应该有更好的方法,但是我没时间去看。我的4Sum的算法是直接衍生于3Sum的。
我在3Sum里面是这么写的:
1、首先就是排序了,毕竟排序后方便找,也符合题目给的不降序的输出
2、选择一个值作为基准(位置i),然后在这个值后面(i+1)和末尾(n-1)分别初始化两个指针p q 3、判断i p
q位置的值大小是否等于target,如果等于就输出一个(然后随便改变p++或q–),如果小于那么p++,如果大于那么q–。
4、上述过程中一直执行到p==q的时候,那么又回到i,选择下一个基准位置。
特别注意: 1、注意i p q的取值范围 2、为了防止重复,在移动第一个
第二个指针的时候,如果遇到移动后和移动前一样,那么记得要做一个移动,直到和上一个取值不一样为止
而在4sum里面我的做法类似,简略说下不同的地方,请对照上面的内容:
1、排序,同3sum
2、在3sum只有一个i基准的情况下,两个循环嵌套,分别为i,和j,对应两个基准值,然后再初始化两个指针p和q,剩下的做法和3sum一样
3、4完全同3sum一样,只是变成i j p q四个位置的和相加就可以
那么4sum同样有防止重复的策略,我的策略同3sum一样,除了q(最后一个)移动的时候不检测,其余的i j q移动的时候,移动的下一位要是一个全新的值,不能移动后值不改变
PS:我代码用的是a b ,解题报告里用的是p q,自己对照就好
1.5 K-Sum
那么现在如果推导到K-Sum问题,那么按照这个套路(虽然不一定最优,但是很容易想到也很好啊),做法是:1、排序
2、前K-2个数使用循环遍历组合
3、最后两个数,在2选择剩余的区间内,设立p q指针,指向首尾,此时如果K个位置的和小于目标值,p++(注意条件4),大于的话 q–,等于的话输出。知道p>=q位置
4、在改变前K-1个的指针时,如果移动后和移动前的值一样,那么要继续移动,直到不一样。。即前K-1个再做++等运算时都必须考虑到4这个条件。
2 原题
原题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)
3 AC解
public class Solution { /** * 2sum 3sum的变种版 * */ public List<List<Integer>> fourSum(int[] nums, int target) { List<List<Integer>> result=new ArrayList<List<Integer>>(); Arrays.sort(nums); int i,j,a,b,reserve; for( i=0;i<nums.length-3;i++){ for( j=i+1;j<nums.length-2;j++){ a=j+1; b=nums.length-1; reserve=target-nums[i]-nums[j]; while(a<b){ if(nums[a]+nums[b]>reserve){ b--; continue; } if(reserve==nums[a]+nums[b]){ ArrayList<Integer> item=new ArrayList<Integer>(); item.add(nums[i]); item.add(nums[j]); item.add(nums[a]); item.add(nums[b]); result.add(item); } a++; while(nums[a]==nums[a-1] && a<b ){ a++; } } while(nums[j]==nums[j+1] && j<nums.length-2){ j++; } } while(nums[i]==nums[i+1] && i<nums.length-3 ){ i++; } } return result; } }
相关文章推荐
- 第三周项目一-个人所得税计算器
- 任务十一:移动Web页面布局实践
- HDU 2795 Billboard(线段树,单点查询)
- C++的深拷贝实现
- 高项2016-03-14
- java对象数组
- android 手把手教您自定义ViewGroup(一)
- java 读取mysql库表数据
- IT行业2016研究分析
- 寄生组合继承
- maven的安装与测试(1)
- C++实现日期类
- BZOJ4390Max Flow
- 虚拟机的三种网络模式
- 关于HTML
- seajs的使用
- 解决在weblogic(可能与之无关)下jsp通过post传递中文内容表单乱码问题
- Problem B
- 机房重构之导出Excel表
- AppInterface,一套Android与H5的混合开发框架