Leetcode[陣列] 18. 四數之和

kev_gogo發表於2020-11-09

Leetcode[陣列] 18. 四數之和

審題

給定一個包含 n 個整數的陣列 nums 和一個目標值 target,判斷 nums 中是否存在四個元素 a,b,c 和 d ,使得 a + b + c + d 的值與 target 相等?找出所有滿足條件且不重複的四元組。

注意:

答案中不可以包含重複的四元組。

示例:

給定陣列 nums = [1, 0, -1, 0, -2, 2],和 target = 0。

滿足要求的四元組集合為:
[
  [-1,  0, 0, 1],
  [-2, -1, 1, 2],
  [-2,  0, 0, 2]
]

看到這道題,依舊是想到了之前的三數之和即雙指標解法,和之前那道題不同的是,這道題是四個數,也就是需要更多的計算量。在一開始,我依舊想的是用 O ( n 2 ) O(n^2) O(n2)解決這道題,即在外迴圈用一個雙指標,在內迴圈也用一個雙指標,但是對於外面的邊界條件始終是想不出來,後來忍不住看了一眼官方題解,好傢伙,官方的題解都是 O ( n 3 ) O(n^3) O(n3),於是徹底打消了兩個雙指標的想法改為二重迴圈遍歷四個數字中的第一個和最後一個元素,內部兩個元素依舊是採用雙指標的辦法。

程式碼實現

class Solution {
public:
    vector<vector<int>> fourSum(vector<int>& nums, int target) {
        vector<vector<int>> fin;
        if ( nums.size()<4 ) return fin;
        int n=nums.size();
        int sum=nums[0]+nums[1]+nums[2]+nums[3];
        sort(nums.begin(), nums.end());
        for ( int i=0; i<n-3; i++ ) {
            for ( int j=n-1; j>i+2; j-- ) {
            int m=j-1;
            int k=i+1;
            while ( k<m ) {
                sum=nums[i]+nums[k]+nums[m]+nums[j];
                if ( sum == target ) {
                    vector<int> tempvec;
                    tempvec.push_back(nums[i]);
                    tempvec.push_back(nums[k]);
                    tempvec.push_back(nums[m]);
                    tempvec.push_back(nums[j]);
                    fin.push_back(tempvec);
                    while ( nums[k] == nums[k+1] && k<m ) k++;
                    while ( nums[m] == nums[m-1] && k<m ) m--;
                    k++;
                } else if ( sum > target ) {
                    m--;
                } else {
                    k++;
                }
            }
            }
        }  
        set<vector<int>> s(fin.begin(), fin.end());
        fin.assign(s.begin(),s.end()); 
        return fin;
    }
};

在這段程式碼中,值得注意的是,我為了去重,並沒有像Leetcode上大多數題解一樣設定許多迴圈去檢查數有沒有變化,而是直接將資料儲存到了set裡再轉到vector…算是偷了個小懶,好處就是邏輯清晰了一些吧。

反思

這幾道陣列題,都是對雙指標的應用,熟練掌握其用法,10min內搞定一道不是問題。

相關文章