FourSum

給定一個包含 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]
]

來源:力扣(LeetCode)

分析一

與TwoSum的思想相似,通過計算兩數之和並將(nums[i]+nums[j],(i,j))鍵值對記錄在map中,從生成的鍵值對中遍歷,再搜索另一個key相加等於target的鍵值對,化爲兩數之和。

兩數之和的博客:兩數之和

  • tips
  1. 使用unordered_multimap可以存儲重複的關鍵字。
    multimap可以存儲重複的key,但是不能重載operator[] ,如 multimap<int,int> mp;mp[key]=1; 這裏的mp[key]=1是不允許的。
  2. 由於等於key的鍵值對可能有多個是,所以用equal_range(key)來訪問查找到的鍵值對,multimap 的find() 查找到的是第一個滿足條件的鍵值對。

代碼

class Solution {
public:
    //使用unordered_multimap存儲可重複的鍵值對 
    //multimap可以存儲重複的key,但是不能重載operator[] ,如 multimap<int,int> mp;mp[key]=1; //mp[key]=1是不允許的
    vector<vector<int>> fourSum(vector<int>& nums, int target) {
        vector<vector<int>> res;
        if(nums.size()<4) return res;
        unordered_multimap<int,pair<int,int>> mp;
        int numsSize=nums.size();
        for(int i=0;i<numsSize;i++)
            for(int j=i+1;j<numsSize;j++){
                mp.insert(make_pair(nums[i]+nums[j],make_pair(i,j)));
            }    
        for(auto it1=mp.begin();it1!=mp.end();it1++){
                int key=target-it1->first;
                auto range=mp.equal_range(key); 
            //由於等於key的鍵值對可能有多個是,所以用equal_range(key)來訪問查找到的鍵值對
            //multimap 的find() 查找到的是第一個滿足條件的鍵值對
            for(auto it2=range.first;it2!=range.second;it2++){
                    auto i=it1->second.first;
                    auto j=it1->second.second;  
                    auto c=it2->second.first;
                    auto d=it2->second.second;

                    if(i!=c&&i!=d&&j!=c&&j!=d){
                        vector<int> tmp{nums[i],nums[j],nums[c],nums[d]};
                        sort(tmp.begin(),tmp.end());
                        res.push_back(tmp);
                    }
                }
            }
        sort(res.begin(),res.end());
        res.erase(unique(res.begin(),res.end()),res.end());
        return res;
    }
};

分析二

與三數之和的思想類比,先用二重循環獲得num[i]、nums[j],再通過雙指針法使用三數之和的方法查找 nums[j]+nums[left]+nums[right]==target-nums[i]。

上一篇三數之和的博客:三數之和

代碼

class Solution {
public:
    
    vector<vector<int>> fourSum(vector<int>& nums, int target) {
        vector<vector<int>> res;
        if(nums.size()<4) return res;
      
        int numsSize=nums.size();
        sort(nums.begin(),nums.end());
      
        for(int i=0;i<numsSize-3;i++){
        
            if(i!=0&&nums[i]==nums[i-1]) continue;
        
            int min=nums[i]+nums[i+1]+nums[i+2]+nums[i+3];
            if(min>target) continue; //是continue不是break!
        
            int max=nums[i]+nums[numsSize-1]+nums[numsSize-2]+nums[numsSize-3];
            if(max<target) continue;
        
            for(int j=i+1;j<numsSize-2;j++){
                if(j>i+1&&nums[j]==nums[j-1]) continue;
        
                int min=nums[i]+nums[j]+nums[j+1]+nums[j+2];
                if(min>target) continue;
        
                int max=nums[i]+nums[j]+nums[numsSize-1]+nums[numsSize-2];
                if(max<target) continue;



                int left=j+1,right=numsSize-1;
        
                while(left<right){
                    int sum=nums[i]+nums[j]+nums[left]+nums[right];
                    if(sum==target){
                        vector<int> tmp{nums[i],nums[j],nums[left],nums[right]};
                        res.push_back(tmp);
                        int dup1=nums[left];
                        int dup2=nums[right];
       
                        while(left<right&&nums[left]==dup1) left++;
                        while(left<right&&nums[right]==dup2) right--;

                    }else if(sum<target)
                         left++; 
					else
                         right--;
                }
            }
        }
       
        return res;
    }
};
發佈了38 篇原創文章 · 獲贊 13 · 訪問量 4023
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章