首页 > 代码库 > [leetcode]4Sum

[leetcode]4Sum

4Sum

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:

  • 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)

思路1:
与之前的[leetcode]3Sum类似,加一层外部循环,时间复杂度为O(n ^ 3)
代码如下:
 1 public class Solution { 2     public List<List<Integer>> fourSum(int[] num, int target) { 3         List<List<Integer>> result = new ArrayList<List<Integer>>(); 4         if(num == null || num.length < 4) return result; 5         int length = num.length; 6         Arrays.sort(num); 7         for (int i = 0; i < length - 3; i++) { 8             if(i > 0 && num[i] == num[i - 1])continue; 9             int one = i;10             for (int j = i + 1; j < length - 2; j++) {11                 if(j > i + 1 && num[j] == num[j - 1])continue;12                 int two = j;13                 int three = j + 1;14                 int four = length - 1;15                 while (three < four) {16                     int sum = num[one] + num[two] + num[three] + num[four];17                     if(sum < target) three++;18                     else if(sum > target) four--;19                     else{20                         List<Integer> list = new ArrayList<Integer>();21                         list.add(num[one]);22                         list.add(num[two]);23                         list.add(num[three]);24                         list.add(num[four]);25                         result.add(list);26                         three++;27                         four--;28                     while(three < four && num[three] == num[three-1]) three++;29                         while(three < four &&num[four] == num[four+1]) four--;30                     }31                 }32             }33         }34         return result;35     }36 }

【吐槽】第一次做这道题的时候,怎么也想不到O(n ^ 3)居然能过,绞尽乳汁【(⊙o⊙)好邪恶】想怎么才能把时间复杂度压缩到O(n ^ 2),我相信面试的时候要求肯定也是O(n^2),因此查了网上的一些大神的思路,对本题做了进一步的优化

思路2:

1. 计算出数组中两两元素的和,把这种二度元素成为nodeOfTwo(学过排列组合的话,应该可以想象到这个数有多大,没办法,空间换时间吧)

2. 对每一个nodeOfTwo元素进行遍历,类似于求[leetcode]Two Sum

2.1 如果存在两个nodeOfTwo元素的和为target,即找到了满足条件的四个元素。

2.2 nodeOfTwo的value毫无疑问是一个list

疑问:

1. 如何去除相同元素?对于nodeOfTwo - 3【何为3的元素对组合】中可能包含两对或以上(0,3)

2. 如何去除重复元素?对于不同的nodeOfTwo节点的组合,还可能有重复,例如nodeOfTwo - 1 和nodeOfTwo - 4包含一个组合(0,1,1,3)但是nodeOfTwo - 3 和nodeOfTwo - 2 中可能包含(0,3,1,1)事实上是重复元素。

代码如下:

 

 1 public List<List<Integer>> fourSum(int[] num, int target) { 2         List<List<Integer>> result = new ArrayList<List<Integer>>(); 3         if(num == null || num.length < 4) return result; 4         int length = num.length; 5         Arrays.sort(num); 6         Map<Integer,List<int[]>> hash = new HashMap<Integer,List<int[]>>(); 7         for(int i = 0; i < length - 1;i++){ 8             for(int j = i + 1; j < length; j++){ 9                 int sum = num[i] + num[j];10                 if(hash.get(sum) == null){11                     List<int[]> list = new ArrayList<int[]>();12                     list.add(new int[]{i,j});13                     hash.put(sum, list);14                 }else{15                     hash.get(sum).add(new int[]{i,j});16                 }17             }18         }19         for(int nodeOfTwo : hash.keySet()){20             if(hash.containsKey(target - nodeOfTwo)){21                 for(int[] oneAndTwo : hash.get(nodeOfTwo)){22                     for(int[] threeAndFour : hash.get(target - nodeOfTwo)){23                         if(oneAndTwo[0] == threeAndFour[0] || oneAndTwo[0] == threeAndFour[1] || oneAndTwo[1] == threeAndFour[0] || oneAndTwo[1] == threeAndFour[1] )continue;//去除重复元素24                         int[] node = {num[oneAndTwo[0]],num[oneAndTwo[1]],num[threeAndFour[0]],num[threeAndFour[1]]};25                         Arrays.sort(node);26                         boolean exist = false;27                         for(List<Integer> tem : result){//去除相同元素28                             int count = 0;29                             for(int i = 0; i < 4; i++){30                                 if(node[i] == tem.get(i))count++;31                             }32                             if(count == 4) exist = true;33                         }34                         if(!exist) {35                             List<Integer> list = new ArrayList<Integer>();36                             for(int i = 0; i < 4; list.add(node[i++]));37                             result.add(list);38                         }39                     }40                 }41             }42         }43         return result;44     }

【吐槽】代码还是太丑了,哎,不过与之前的相比还是稍微好点的,慎重点击->[leetcode]4Sum