4Sum -- LeetCode
原题链接: http://oj.leetcode.com/problems/4sum/
这道题要求跟3Sum差点儿相同,仅仅是需求扩展到四个的数字的和了。我们还是能够依照3Sum中的解法,仅仅是在外面套一层循环。相当于求n次3Sum。我们知道3Sum的时间复杂度是O(n^2),所以假设这样解的总时间复杂度是O(n^3)。代码例如以下:
public ArrayList<ArrayList<Integer>> fourSum(int[] num, int target) {
ArrayList<ArrayList<Integer>> res = new ArrayList<ArrayList<Integer>>();
if(num==null||num.length==0)
return res;
Arrays.sort(num);
for(int i=num.length-1;i>2;i--)
{
if(i==num.length-1 || num[i]!=num[i+1])
{
ArrayList<ArrayList<Integer>> curRes = threeSum(num,i-1,target-num[i]);
for(int j=0;j<curRes.size();j++)
{
curRes.get(j).add(num[i]);
}
res.addAll(curRes);
}
}
return res;
}
private ArrayList<ArrayList<Integer>> threeSum(int[] num, int end, int target)
{
ArrayList<ArrayList<Integer>> res = new ArrayList<ArrayList<Integer>>();
for(int i=end;i>1;i--)
{
if(i==end || num[i]!=num[i+1])
{
ArrayList<ArrayList<Integer>> curRes = twoSum(num,i-1,target-num[i]);
for(int j=0;j<curRes.size();j++)
{
curRes.get(j).add(num[i]);
}
res.addAll(curRes);
}
}
return res;
}
private ArrayList<ArrayList<Integer>> twoSum(int[] num, int end, int target)
{
ArrayList<ArrayList<Integer>> res = new ArrayList<ArrayList<Integer>>();
int l=0;
int r=end;
while(l<r)
{
if(num[l]+num[r]==target)
{
ArrayList<Integer> item = new ArrayList<Integer>();
item.add(num[l]);
item.add(num[r]);
res.add(item);
l++;
r--;
while(l<r&&num[l]==num[l-1])
l++;
while(l<r&&num[r]==num[r+1])
r--;
}
else if(num[l]+num[r]>target)
{
r--;
}
else
{
l++;
}
}
return res;
}
上述这样的方法比較直接。依据3Sum的结果非常easy进行推广。那么时间复杂度能不能更好呢?事实上我们能够考虑用二分法的思路,假设把全部的两两pair都求出来。然后再进行一次Two
Sum的匹配。我们知道Two
Sum是一个排序加上一个线性的操作,而且把全部pair的数量是O((n-1)+(n-2)+...+1)=O(n(n-1)/2)=O(n^2)。
所以对O(n^2)的排序假设不用特殊线性排序算法是O(n^2*log(n^2))=O(n^2*2logn)=O(n^2*logn),算法复杂度比上一个方法的O(n^3)是有提高的。
思路尽管明白,只是细节上会多非常多情况要处理。
首先。我们要对每个pair建一个数据结构来存储元素的值和相应的index,这样做是为了后面当找到合适的两对pair相加能得到target值时看看他们是否有重叠的index,假设有说明它们不是合法的一个结果,由于不是四个不同的元素。接下来我们还得对这些pair进行排序。所以要给pair定义comparable的函数。最后。当进行Two
Sum的匹配时由于pair不再是一个值,所以不能像Two
Sum中那样直接跳过同样的。每一组都得进行查看,这样就会出现反复的情况,所以我们还得给每个四个元素组成的tuple定义hashcode和相等函数,以便能够把当前求得的结果放在一个HashSet里面,这样得到新结果假设是反复的就不增加结果集了。
代码例如以下:
private ArrayList<ArrayList<Integer>> twoSum(ArrayList<Pair> pairs, int target){
HashSet<Tuple> hashSet = new HashSet<Tuple>();
int l = 0;
int r = pairs.size()-1;
ArrayList<ArrayList<Integer>> res = new ArrayList<ArrayList<Integer>>();
while(l<r){
if(pairs.get(l).getSum()+pairs.get(r).getSum()==target)
{
int lEnd = l;
int rEnd = r;
while(lEnd<rEnd && pairs.get(lEnd).getSum()==pairs.get(lEnd+1).getSum())
{
lEnd++;
}
while(lEnd<rEnd && pairs.get(rEnd).getSum()==pairs.get(rEnd-1).getSum())
{
rEnd--;
}
for(int i=l;i<=lEnd;i++)
{
for(int j=r;j>=rEnd;j--)
{
if(check(pairs.get(i),pairs.get(j)))
{
ArrayList<Integer> item = new ArrayList<Integer>();
item.add(pairs.get(i).nodes[0].value);
item.add(pairs.get(i).nodes[1].value);
item.add(pairs.get(j).nodes[0].value);
item.add(pairs.get(j).nodes[1].value);
//Collections.sort(item);
Tuple tuple = new Tuple(item);
if(!hashSet.contains(tuple))
{
hashSet.add(tuple);
res.add(tuple.num);
}
}
}
}
l = lEnd+1;
r = rEnd-1;
}
else if(pairs.get(l).getSum()+pairs.get(r).getSum()>target)
{
r--;
}
else{
l++;
}
}
return res;
}
private boolean check(Pair p1, Pair p2)
{
if(p1.nodes[0].index == p2.nodes[0].index || p1.nodes[0].index == p2.nodes[1].index)
return false;
if(p1.nodes[1].index == p2.nodes[0].index || p1.nodes[1].index == p2.nodes[1].index)
return false;
return true;
}
另外一种方法比第一种方法时间上还是有提高的,事实上这道题能够推广到k-Sum的问题。基本思想就是和另外一种方法一样进行二分。然后两两结合,只是细节就非常复杂了(这点从上面的另外一种解法就能看出来),所以不是非常适合在面试中出现。有兴趣的朋友能够进一步思考或者搜索网上材料哈。
4Sum -- LeetCode的更多相关文章
- 4Sum——LeetCode
Given an array S of n integers, are there elements a, b, c, and d in S such that a + b + c + d = tar ...
- LeetCode 解题报告索引
最近在准备找工作的算法题,刷刷LeetCode,以下是我的解题报告索引,每一题几乎都有详细的说明,供各位码农参考.根据我自己做的进度持续更新中...... ...
- Solution to LeetCode Problem Set
Here is my collection of solutions to leetcode problems. Related code can be found in this repo: htt ...
- [LeetCode] 4Sum II 四数之和之二
Given four lists A, B, C, D of integer values, compute how many tuples (i, j, k, l) there are such t ...
- [LeetCode] 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 ...
- 求和问题总结(leetcode 2Sum, 3Sum, 4Sum, K Sum)
转自 http://tech-wonderland.net/blog/summary-of-ksum-problems.html 前言: 做过leetcode的人都知道, 里面有2sum, 3sum ...
- [LeetCode][Python]18: 4Sum
# -*- coding: utf8 -*-'''__author__ = 'dabay.wang@gmail.com' 18: 4Sumhttps://oj.leetcode.com/problem ...
- LeetCode之“散列表”:Two Sum && 3Sum && 3Sum Closest && 4Sum
1. Two Sum 题目链接 题目要求: Given an array of integers, find two numbers such that they add up to a specif ...
- leetcode — 4sum
import java.util.Arrays; import java.util.HashSet; import java.util.Set; /** * Source : https://oj.l ...
随机推荐
- Android 开发之网易云音乐(或QQ音乐)的播放界面转盘和自定义SeekBar的实现
这个东西我在eoeAndroid上首发的,但没有详细的实现说明:http://www.eoeandroid.com/thread-317901-1-1.html 在csdn上进行详细的说明吧.(同时上 ...
- ViewPager引导页效果实例源码
首先大家先找到本地的sdk,然后找到Google提供的API,具体查找方法如下:sdk——>docs——>index.html——>develop——>training——&g ...
- iOS 如何自定义NavigationBar的高度
UINavigationBar的高度在苹果官方的SDK中是固定的44个点,但是实际项目中我们却有可能遇到这样的情况,如下图: 这样的一个UINavigationBar的高度达到了84个点,这就需要我们 ...
- TTL电平与RS232电平的区别
TTL电平与RS232电平的区别 工作中遇到一个关于电平选择的问题,居然给忘记RS232电平的定义了,当时无法反应上来,回来之后查找资料才了解两者之间的区别,视乎两年多的时间,之前非常熟悉的一些常 ...
- 机器学习笔记(二)- from Andrew Ng的教学视频
省略了Octave的使用方法结束,以后用得上再看吧 week three: Logistic Regression: 用于0-1分类 Hypothesis Representation: :Sigmo ...
- 在Windows下github展示代码
最近大爱Web编程,于是寻找各种代码中,然后就发现了GitHub这个网站,如果你知道Google Code,那么你就知道这个GitHub是做什么的了.不过GitHub主要是用作基于Git的分布式版本管 ...
- Asp.Net Core
开源Asp.Net Core小型社区系统 源码地址:Github 前言 盼星星盼月亮,Asp.Net Core终于发布啦!! Asp.Net发布时我还在上初中,没有赶上.但是Asp.Net Core我 ...
- 整数运算:CPU内部只有加法运算
学汇编的一边儿去.我这里讲的是CPU进行计算的原理.首先我这里用MC的红石电路模拟了一个加法器:http://www.0xaa55.com/thread-313-1-1.htm首先加法器是怎么实现的呢 ...
- docker 学习笔记21:docker连接网络的设置
1.如果docker主机不需要通过代理连接外网 则docker的相关命令(如docker search)或docker容器与网络相关的操作都可以正常进行,不需要特殊设置. 2.当docker主机 是通 ...
- Android的BUG(二) - SurfaceTexture中的野指针
当初遇到这个bug,是不定期的低概率出现,最后找到一个比较容易重现的步骤: 启动系统 然后进google + 新建一个帐号(注意是新建一个帐号) 没几步就重启了 这个BUG,一开始追踪也是无头绪的 ...