[LeetCode] 18. 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: 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: 

  在 3Sum 的基礎上再加一層循環即可,3Sum 時間復雜度為 O(n2),所以這個方法時間復雜度為 O(n3)。

public class Solution {
    public List<List<Integer>> fourSum(int[] nums, int target) {
        List<List<Integer>> res = new ArrayList<>();
        if (nums == null || nums.length < 4) {
            return res;
        }
        
        Arrays.sort(nums);
        for (int i = 0; i < nums.length - 3; i++) {
            if (i > 0 && nums[i] == nums[i - 1]) {
                continue;
            }
            
            int sum3 = target - nums[i];  // 后3個數之和需等於sum3
            for (int j = i + 1; j < nums.length - 2; j++) {
                if (j > i + 1 && nums[j] == nums[j - 1]) {
                    continue;
                }
                
                int sum2 = sum3 - nums[j];  // 后2個數之和需等於sum3
                int left = j + 1, right = nums.length - 1;
                
                while (left < right) {
                    if (nums[left] + nums[right] == sum2) {
                        List<Integer> quad = new ArrayList<>();
                        quad.add(nums[i]);
                        quad.add(nums[j]);
                        quad.add(nums[left]);
                        quad.add(nums[right]);
                        res.add(quad);
                        
                        while (left < right && nums[left++] == nums[left]) {}
                        while (left < right && nums[right--] == nums[right]) {}
                        
                    } else if (nums[left] + nums[right] < sum2) {
                        while (left < right && nums[left++] == nums[left]) {}
                        
                    } else {
                        while (left < right && nums[right--] == nums[right]) {}
                    }
                }
            }
        }
        return res;
    }
}

 

 

解法2: 

  先排序 (O(nlogn)),然后遍歷整個數組,以每兩個數的和作為key將兩個數的index存於HashMap中,由於存在和相同的情況,因此HashMap中的每個鍵對應的是一個List,每個List中保存着多組index對,這一操作時間復雜度為 (O(n2))。

  遍歷每個key,計算出需要滿足4Sum為target的另外一個2Sum,兩個2Sum對應的List分別為listA和listB,遍歷其中的每一組index,分別為[a0, a1] 和 [b0, b1]。為避免找到index重復的結果,只尋找滿足 a0 < b0, a0 < b1, a1 < b0, a1 < b1 的結果,而因為本身就有 a0 < a1, b0 < b1,所以只需滿足 a1 < b0 即可。判斷找到的結果是否已存在,不存在再把結果加到res中。這一操作比較復雜,時間復雜度不好算,據說是(O(n2logn)),但LeetCode給出的結果是超時。。。。

public class Solution {
    public List<List<Integer>> fourSum(int[] nums, int target) {
        List<List<Integer>> res = new ArrayList<>();
        if (nums == null || nums.length < 4) {
            return res;
        }
        
        Arrays.sort(nums);
        
        HashMap<Integer, List<Integer[]>> map = new HashMap<>();
        for (int i = 0; i < nums.length - 1; i++) {
            for (int j = i + 1; j < nums.length; j++) {
                int sum = nums[i] + nums[j];
                Integer[] pair = {i, j};
                
                if (!map.containsKey(sum)) {
                    map.put(sum, new ArrayList<Integer[]>());
                }
                map.get(sum).add(pair);
            }
        }
        
        Set<Integer> keys = map.keySet();
        for (int key : keys) {
            List<Integer[]> listA = map.get(key);
            List<Integer[]> listB = map.get(target - key);
            
            if (listA != null && listB != null) {
                for (Integer[] pairA : listA) {
                    int a0 = pairA[0], a1 = pairA[1];
                    
                    for (Integer[] pairB : listB) {
                        int b0 = pairB[0], b1 = pairB[1];
                        if (a1 < b0) {  // 因為肯定存在: a0 < a1, b0 < b1
                            List<Integer> list = new ArrayList<>();
                            list.add(nums[a0]);
                            list.add(nums[a1]);
                            list.add(nums[b0]);
                            list.add(nums[b1]);
                            if (!res.contains(list)) res.add(list);
                        }
                    }
                }
            }
        }
        
        return res;
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM