码迷,mamicode.com
首页 > 其他好文 > 详细

Leetcode: 4Sum

时间:2014-10-12 06:27:07      阅读:248      评论:0      收藏:0      [点我收藏+]

标签:des   style   blog   http   color   io   os   ar   for   

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)

可以按照3Sum的思路来做,并以此类推,KSum的复杂度就是O(N^(k-1)). 在3Sum外面再套一层循环,相当于N次求3Sum

 1 public class Solution {
 2     public ArrayList<ArrayList<Integer>> fourSum(int[] num, int target) {
 3         ArrayList<ArrayList<Integer>> res = new ArrayList<ArrayList<Integer>>();
 4         if (num==null || num.length==0) return res;
 5         Arrays.sort(num);
 6         for (int i=num.length-1; i>=3; i--) {
 7             if (i<num.length-1 && num[i]==num[i+1]) continue;
 8             ArrayList<ArrayList<Integer>> sets = threeSum(0, i-1, num, target-num[i]);
 9             for (int ii=0; ii<sets.size(); ii++) {
10                 ArrayList<Integer> temp = sets.get(ii);
11                 temp.add(num[i]);
12             }
13             res.addAll(sets);
14         }
15         return res;
16     }
17     
18     public ArrayList<ArrayList<Integer>> threeSum(int start, int end, int[] num, int target) {
19         ArrayList<ArrayList<Integer>> res = new ArrayList<ArrayList<Integer>>();
20         for (int j=end; j>=2; j--) {
21             if (j<end && num[j]==num[j+1]) continue;
22             ArrayList<ArrayList<Integer>> sets = twoSum(0, j-1, num, target-num[j]);
23             for (int jj=0; jj<sets.size(); jj++) {
24                 ArrayList<Integer> temp = sets.get(jj);
25                 temp.add(num[j]);
26             }
27             res.addAll(sets);
28         }
29         return res;
30     }
31     
32     public ArrayList<ArrayList<Integer>> twoSum(int l, int r, int[] num, int target) {
33         ArrayList<ArrayList<Integer>> res = new ArrayList<ArrayList<Integer>>();
34         while (l < r) {
35             if (num[l]+num[r] == target) {
36                 ArrayList<Integer> set = new ArrayList<Integer>();
37                 set.add(num[l]);
38                 set.add(num[r]);
39                 res.add(new ArrayList<Integer>(set));
40                 l++;
41                 r--;
42                 while (l<r && num[l] == num[l-1]) {
43                     l++;
44                 }
45                 while (l<r && num[r] == num[r+1]) {
46                     r--;
47                 }
48             }
49             else if (num[l]+num[r] < target) {
50                 l++;
51             }
52             else {
53                 r--;
54             }
55         }
56         return res;
57     }
58 }

(未深究)网上还看到一种方法,就是如果想那么时间复杂度更好的话,其实我们可以考虑用二分法的思路,如果把所有的两两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里面,这样得到新结果如果是重复的就不加入结果集了。

 1 private ArrayList<ArrayList<Integer>> twoSum(ArrayList<Pair> pairs, int target){
 2     HashSet<Tuple> hashSet = new HashSet<Tuple>();
 3     int l = 0;
 4     int r = pairs.size()-1;
 5     ArrayList<ArrayList<Integer>> res = new ArrayList<ArrayList<Integer>>();
 6     while(l<r){
 7         if(pairs.get(l).getSum()+pairs.get(r).getSum()==target)
 8         {
 9             int lEnd = l;
10             int rEnd = r;
11             while(lEnd<rEnd && pairs.get(lEnd).getSum()==pairs.get(lEnd+1).getSum())
12             {
13                 lEnd++;
14             }
15             while(lEnd<rEnd && pairs.get(rEnd).getSum()==pairs.get(rEnd-1).getSum())
16             {
17                 rEnd--;
18             }
19             for(int i=l;i<=lEnd;i++)
20             {
21                 for(int j=r;j>=rEnd;j--)
22                 {
23                     if(check(pairs.get(i),pairs.get(j)))
24                     {
25                         ArrayList<Integer> item = new ArrayList<Integer>();
26                         item.add(pairs.get(i).nodes[0].value);
27                         item.add(pairs.get(i).nodes[1].value);
28                         item.add(pairs.get(j).nodes[0].value);
29                         item.add(pairs.get(j).nodes[1].value);
30                         //Collections.sort(item);
31                         Tuple tuple = new Tuple(item);
32                         if(!hashSet.contains(tuple))
33                         {
34                             hashSet.add(tuple);
35                             res.add(tuple.num);
36                         }
37                     }                        
38                 }
39             }
40             l = lEnd+1;
41             r = rEnd-1;
42         }
43         else if(pairs.get(l).getSum()+pairs.get(r).getSum()>target)
44         {
45             r--;
46         }
47         else{
48             l++;
49         }
50     }
51     return res;
52 }
53 private boolean check(Pair p1, Pair p2)
54 {
55     if(p1.nodes[0].index == p2.nodes[0].index || p1.nodes[0].index == p2.nodes[1].index)
56         return false;
57     if(p1.nodes[1].index == p2.nodes[0].index || p1.nodes[1].index == p2.nodes[1].index)
58         return false;
59     return true;
60 }

 

Leetcode: 4Sum

标签:des   style   blog   http   color   io   os   ar   for   

原文地址:http://www.cnblogs.com/EdwardLiu/p/4020087.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!