[LeetCode] 4Sum 四數之和

Grandyang發表於2015-05-19

 

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

 

LeetCode中關於數字之和還有其他幾道,分別是 Two Sum ,3Sum ,3Sum Closest ,雖然難度在遞增,但是整體的套路都是一樣的,在這裡為了避免重複項,我們使用了STL中的set,其特點是不能有重複,如果新加入的數在set中原本就存在的話,插入操作就會失敗,這樣能很好的避免的重複項的存在。此題的O(n^3)解法的思路跟 3Sum 基本沒啥區別,就是多加了一層for迴圈,其他的都一樣,程式碼如下:

 

解法一:

class Solution {
public:
    vector<vector<int>> fourSum(vector<int> &nums, int target) {
        set<vector<int>> res;
        sort(nums.begin(), nums.end());
        for (int i = 0; i < int(nums.size() - 3); ++i) {
            for (int j = i + 1; j < int(nums.size() - 2); ++j) {
                if (j > i + 1 && nums[j] == nums[j - 1]) continue;
                int left = j + 1, right = nums.size() - 1;
                while (left < right) {
                    int sum = nums[i] + nums[j] + nums[left] + nums[right];
                    if (sum == target) {
                        vector<int> out{nums[i], nums[j], nums[left], nums[right]};
                        res.insert(out);
                        ++left; --right;
                    } else if (sum < target) ++left;
                    else --right;
                }
            }
        }
        return vector<vector<int>>(res.begin(), res.end());
    }
};

 

但是畢竟用set來進行去重複的處理還是有些取巧,可能在Java中就不能這麼做,那麼我們還是來看一種比較正統的做法吧,手動進行去重複處理。主要可以進行的有三個地方,首先在兩個for迴圈下可以各放一個,因為一旦當前的數字跟上面處理過的數字相同了,那麼找下來肯定還是重複的。之後就是當sum等於target的時候了,我們在將四個數字加入結果res之後,left和right都需要去重複處理,分別像各自的方面遍歷即可,參見程式碼如下:

 

解法二:

class Solution {
public:
    vector<vector<int>> fourSum(vector<int> &nums, int target) {
        vector<vector<int>> res;
        int n = nums.size();
        sort(nums.begin(), nums.end());
        for (int i = 0; i < n - 3; ++i) {
            if (i > 0 && nums[i] == nums[i - 1]) continue;
            for (int j = i + 1; j < n - 2; ++j) {
                if (j > i + 1 && nums[j] == nums[j - 1]) continue;
                int left = j + 1, right = n - 1;
                while (left < right) {
                    int sum = nums[i] + nums[j] + nums[left] + nums[right];
                    if (sum == target) {
                        vector<int> out{nums[i], nums[j], nums[left], nums[right]};
                        res.push_back(out);
                        while (left < right && nums[left] == nums[left + 1]) ++left;
                        while (left < right && nums[right] == nums[right - 1]) --right;
                        ++left; --right;
                    } else if (sum < target) ++left;
                    else --right;
                }
            }
        }
        return res;
    }
};

 

類似題目:

Two Sum

3Sum

4Sum II

 

參考資料:

https://leetcode.com/problems/4sum/

https://leetcode.com/problems/4sum/discuss/8549/My-16ms-c%2B%2B-code

https://leetcode.com/problems/4sum/discuss/8575/Clean-accepted-java-O(n3)-solution-based-on-3sum

 

LeetCode All in One 題目講解彙總(持續更新中...)

相關文章