18. 4Sum (JAVA)

Given an array nums of n integers and an integer target, are there elements abc, and d in nums such that a + b + cd = target? Find all unique quadruplets in the array which gives the sum of target.

Note:

The solution set must not contain duplicate quadruplets.

Example:

Given array nums = [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]
]

法I:在3Sum的基础上,多加一个循环。时间复杂度O(n3)。

法II:使用HashTable。O(N^2)把所有pair存入hash表,pair中两个元素的和就是hash值。那么接下来求4sum就变成了在所有的pair value中求 2sum,这个就成了线性算法了。所以整体上这个算法是O(N^2)+O(n) = O(N^2)。

class Solution {
    public List<List<Integer>> fourSum(int[] nums, int target) {
        List<List<Integer>> ret = new ArrayList<>();
        Map<Integer, List<List<Integer>>> twoSum = new HashMap<>();
        Map<Integer, Integer> cnt = new HashMap<>(); //count of each num
        
        //sort array
        Arrays.sort(nums);
    
        for(int i = 0; i < nums.length; i++){
            //update count
            if(cnt.get(nums[i])==null) 
                cnt.put(nums[i],1);
            else
                cnt.put(nums[i],cnt.get(nums[i])+1);
                   
            //initialize map
            if(i>0 && nums[i]==nums[i-1]) continue;//avoid repeat
            for(int j = i+1; j < nums.length; j++){
                if(j > i+1 && nums[j]==nums[j-1]) continue; //avoid repeat
                
                List<Integer> list = new ArrayList<>();
                list.add(nums[i]);
                list.add(nums[j]);
                List<List<Integer>> listGroup = twoSum.get(nums[i]+nums[j]);
                if(listGroup ==null ){
                    listGroup = new ArrayList<>();   
                }
                listGroup.add(list);
                twoSum.put(nums[i]+nums[j], listGroup);
            }
        }
        
        //iterate map to find target sum
        Set<Integer> keys = twoSum.keySet();
        for (int key : keys) {
            List<List<Integer>> listGroupA = twoSum.get(key);
            for(List<Integer> listA: listGroupA){
                List<List<Integer>> listGroupB = twoSum.get(target - key);
                if(listGroupB == null) continue;
                for(List<Integer> listB: listGroupB){
                    //check whether count of num is enough
                    int a = listA.get(0);
                    int b = listA.get(1);
                    int c = listB.get(0);
                    int d = listB.get(1);
                    if(Math.max(a,b) > Math.min(c,d)) continue; //四个数两两组合,有6种情况,这里只取两个最小的数在listA的情况,去重

                    //check count of num
                    cnt.put(a,cnt.get(a)-1);
                    cnt.put(b,cnt.get(b)-1);
                    cnt.put(c,cnt.get(c)-1);
                    cnt.put(d,cnt.get(d)-1);
                    if(cnt.get(a) >= 0 && cnt.get(b) >= 0 && cnt.get(c) >= 0 && cnt.get(d) >= 0){
                        //find one list
                        List<Integer> listC = new ArrayList<>();
                        listC.addAll(listA);
                        listC.addAll(listB);
                        ret.add(listC);
                    }

                    //recover count of num
                    cnt.put(a,cnt.get(a)+1);
                    cnt.put(b,cnt.get(b)+1);
                    cnt.put(c,cnt.get(c)+1);
                    cnt.put(d,cnt.get(d)+1);
                }
            }   
        } 
        return ret;
        
    }
}

猜你喜欢

转载自www.cnblogs.com/qionglouyuyu/p/10774834.html