Leetcode1.Two Sum+LeetCode15.3Sum+LeetCode18. 4Sum【K-Sum問題】

題目鏈接https://leetcode.com/problems/two-sum/  (2-sum)


Given an array of integers, return indices of the two numbers such that they add up to a specific target.

You may assume that each input would have exactly one solution.

Example:

Given nums = [2, 7, 11, 15], target = 9,

Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1].

解題思路:對於2-Sum,筆者提供兩種版本(二分 +線性查找),兩種版本都是先排序。


線性查找,利用的是一種單調性,比容器盛水那道題(http://blog.csdn.net/u012717411/article/details/53406043)容易理解的多得多,複雜度O(n)。


二分版本O(nlogn)


struct node{
    int val,pos;
    friend bool operator < (node a,node b){
        if(a.val == b.val) return a.pos < b.pos;
        return a.val < b.val;
    } 
};

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        vector<int>ans;
        node p[nums.size()];
        for(int i = 0;i < nums.size();++ i){
            p[i].val = nums[i];
            p[i].pos = i;
        }
        sort(p,p+nums.size());
        bool f = 1;
        for(int i = 0;i < nums.size()&&f;++ i){
            int l = i+1,r = nums.size();
            while(l < r){
                int m = (l + r) >> 1;
                if(p[m].val == target - p[i].val) {
                  ans.push_back(p[i].pos);
                  ans.push_back(p[m].pos);
                  f = 0;
                  break;
                }
                if(p[m].val < target - p[i].val) l = m+1;
                else r = m;
            }
        }
        return ans;
    }
};


線性查找O(n)


struct node{
    int val,id;
    friend bool operator <(node a,node b){
        if(a.val == b.val) return a.id < b.id;
        return a.val < b.val;
    }
};

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) { //排序O(nlogn) + 查找O(n)
        vector<int>ans;
        node p[nums.size()];
        for(int i = 0;i < nums.size();++ i){
            p[i].val = nums[i];
            p[i].id = i;
        }
        sort(p,p+nums.size());
        int l = 0,r = nums.size() - 1;
        while(l < r){
            if(p[l].val + p[r].val == target){
                ans.push_back(min(p[l].id,p[r].id));
                ans.push_back(max(p[l].id,p[r].id));
                break;
            }
            else if(p[l].val + p[r].val > target) r--;
            else l++;
        }
        return ans;
    }
};


題目鏈接https://leetcode.com/problems/3sum/  (3-sum)


Given an array S of n integers, are there elements abc in S such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.

Note: The solution set must not contain duplicate triplets.

For example, given array S = [-1, 0, 1, 2, -1, -4],

A solution set is:
[
  [-1, 0, 1],
  [-1, -1, 2]
]

解題思路:有了2-sum的求解思路,很容易將3-Sum問題轉換成2-Sum。


注意去重的處理,我一開始用二分查找,set去重,結果發現一直TLE;原因就是插入set次數太多,複雜度大於O(n^2log(n))! 


這題必須要O(n^2)的算法才能過,卡set,也附出二分+set的版本:


版本一:二分 + set ( T L E )


class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
     set<vector<int>> tar;
     sort(nums.begin(),nums.end());
     bool f;int l,r;
     for(int i = 0;i < nums.size();++ i){
         for(int j = i+1;j < nums.size();++ j){
             l = j+1,r = nums.size();
             f = 0;
             while(l < r){
                 int m = (l+r) >> 1;
                 if(nums[m] == -nums[i]-nums[j]) {f = 1;break;}
                 if(nums[m] < -nums[i]-nums[j]) l = m+1;
                 else r = m;
             }
             if(f){
                 tar.insert({nums[i],nums[j],-nums[i]-nums[j]});
             } 
         }
     }
     return vector<vector<int>>(tar.begin(),tar.end());
    }
};



版本二:不用set,自己剪枝去重即可,注意可能重複的原因(選取的第一個元素重複;兩個加數重複;);


用set過不了的,可見這題比較卡時間!


2-Sum問題,用線性查找,總複雜度O(n^2)


class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
     vector<vector<int>>ans;
     sort(nums.begin(),nums.end());
    
     for(int i = 0;i < nums.size();++ i){
        if(i && nums[i] == nums[i-1]) continue;//去重
        //if(nums[i] > 0) continue;//剪枝
        int tar = -nums[i];
        int l = i+1,r = nums.size()-1;
        while(l < r){
            if(nums[l] + nums[r] == tar){
                ans.push_back({nums[i],nums[l],nums[r]});
                while(l < r && nums[l] == nums[l+1]) l++;//去重
                while(l < r && nums[r] == nums[r-1]) r--;
                l++;
                r--;
            }
            else if(nums[l] + nums[r] < tar) l++;
            else r--;
        }
     }
    // return vector<vector<int>>(ans.begin(),ans.end());
     return ans;
    }
};


題目鏈接https://leetcode.com/problems/4sum/ (4-Sum)


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]
]

解題思路:4-Sum轉成3-Sum,複雜度O(n^3),注意去重的處理!


參考代碼


class Solution {
public:
    vector<vector<int>> fourSum(vector<int>& nums, int target) {
        vector<vector<int>>ans;
        sort(nums.begin(),nums.end());
        for(int i = 0;i < nums.size();++ i){
            if(i && nums[i] == nums[i-1]) continue;//去重
            for(int j = i+1;j < nums.size();++ j){
                if(j>=i+2 && nums[j] == nums[j-1]) continue;//去重
                int l = j+1,r = nums.size() - 1;
                while(l < r){
                    if(nums[i] + nums[j] + nums[l] + nums[r] == target){
                        ans.push_back({nums[i],nums[j],nums[l],nums[r]});
                        while(l < r && nums[l] == nums[l+1]) ++l;//去重
                        while(l < r && nums[r] == nums[r-1]) --r;
                        ++l;
                        --r;
                    }
                    else if(nums[i] + nums[j] + nums[l] + nums[r] < target) l++;
                    else r--;
                }
            }
        }
        return ans;
    }
};


K Sum 問題


問題描述


   給你一組N個數字(比如 vector<int> num), 然後給你一個常數(比如 int target) ,我們的目標是在這一堆數裏面找到K個數字,使得這K個數字的和等於target;


解題方法


  3-Sum問題轉化成2-Sum問題,4-Sum問題轉成3-Sum問題,.....,K Sum 問題轉換成 K - 1 Sum問題;

  

  2-Sum的求解我們已知,線性查找O(n)。


複雜度

   

  O(n^(k - 1))


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章