2sum 3sum 4sum 各種sum

Two Sum

Given an array of integers, find two numbers such that they add up to a specific target number.

The function twoSum should return indices of the two numbers such that they add up to the target, where index1 must be less than index2. Please note that your returned answers (both index1 and index2) are not zero-based.

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

Input: numbers={2, 7, 11, 15}, target=9
Output: index1=1, index2=2

題目:在一個數組中,找到兩個數的和是target。題目假設僅有一個解。

分析:本來是很簡單的一個題目,排序,然後定義兩個下標i,j分別從頭和尾向中間夾逼,直到找到和爲target的下標。時間複雜度是排序的O(nlogn)。

問題的複雜在於返回下標,因爲排序會打亂下標,因此需要定義一個數據結構來保存下標和對應的值,值排序之後,返回對應的結果。

代碼:

struct Node {
    int val;
    int index;
    Node(int v, int i):val(v),index(i){}
};

bool cmp(const Node &n1, const Node &n2){//比較函數,注意參數要const...
    return (n1.val < n2.val);
}

class Solution {
public:
    vector<int> twoSum(vector<int> &numbers, int target) {
        vector<int> res;
        int len=numbers.size();
        if(len<2) return res;
        vector<Node> tmp;
        for(int x=0;x<len;x++){
            Node n(numbers[x],x);
            //將新的節點push到容器中
            tmp.push_back(n);
        }
        sort(tmp.begin(), tmp.end(),cmp);//排序
        
        int i,j;
        for(i=0,j=len-1;i<j;){//兩下標
            if((tmp[i].val+tmp[j].val)<target){
                i++;
            }else if((tmp[i].val+tmp[j].val)>target){
                j--;
            }else{//==
                if(tmp[i].index<tmp[j].index){//注意結果保證小小標在前
                    res.push_back(tmp[i].index+1);
                    res.push_back(tmp[j].index+1);
                }else{
                    res.push_back(tmp[j].index+1);
                    res.push_back(tmp[i].index+1);
                   
                }      
                break;
            }
        }
        return res;
    }
};

3Sum

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

Note:

  • Elements in a triplet (a,b,c) must be in non-descending order. (ie, abc)
  • 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)
題目:在數組中找到三個數,使和爲0,可能有多組這樣的數滿足結果。

分析:基本思路,固定一個數,然後target減去這個數,轉換成2sum問題,時間複雜度爲O(n*nlogn)。

這裏注意去重,找到一個滿足條件的結果後,要將i之後與當前值相同的 屏蔽掉,j同樣。

代碼:

class Solution {
public:
    vector<vector<int> > threeSum(vector<int> &num) {
        int len=num.size();
        vector<vector<int> > res;
        sort(num.begin(),num.end());
        
        for(int k=0;k<len-2;){
            int t=0-num[k];
            for(int i=k+1,j=len-1;i<j;){//i=k+1!!!!i初始化時錯了,單步調試才發現。。。。
                if((num[i]+num[j])>t) j--;
                else if((num[i]+num[j])<t) i++;
                else{//==
                    vector<int> one;
                    one.push_back(num[k]);
                    one.push_back(num[i]);
                    one.push_back(num[j]);
                    res.push_back(one);
                    i++;j--;
                    while(i<j && num[i]==num[i-1])//去除與當前結果相同的值
                        i++;
                    while(j>i && num[j]==num[j+1])
                        j--;
                }
            }//i,j
            k++;
            while(k<len-2 && num[k]==num[k-1])//外層的k也要進行同樣的處理
                k++;
        }//for k
        return res;
    }
};


3Sum Closest

Given an array S of n integers, find three integers in S such that the sum is closest to a given number, target. Return the sum of the three integers. You may assume that each input would have exactly one solution.

    For example, given array S = {-1 2 1 -4}, and target = 1.

    The sum that is closest to the target is 2. (-1 + 2 + 1 = 2)
題目: 求一個數組中的三個數,他們之和最接近target。

分析:同樣排序,固定一個數,轉換成2sum問題,注意這裏最接近,保存一個dif來記錄最小差值。

代碼:

class Solution {
public:
    int threeSumClosest(vector<int> &num, int target) {
        int len=num.size();
        sort(num.begin(),num.end());
        int closet=0;
        int mindif=INT_MAX;
        for(int i=0;i<len-2;i++){
            int t=target-num[i];
            for(int j=i+1,k=len-1;j<k;){
                int dif=(num[j]+num[k])-t;
                if(abs(dif)<mindif) { //記錄最小差值
                    mindif=abs(dif); 
                    closet=num[i]+num[j]+num[k];
                }
                if(dif<0){
                    j++;
                }else if(dif>0){
                    k--;
                }else{
                    return target;
                }
                //if(abs(dif)<mindif) { //不能放在後面,if會是k的值發生變化
                //    mindif=abs(dif); 
                //    closet=num[i]+num[j]+num[k];//此時k已經發生變化
                //}
                
            }//for j k
            
        }//for i
        return closet;
    }
};

4Sum

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)

題意:從一個數組中,找四個數使其和等於target。

分析:依次固定兩個數,也變成2sum的問題,時間複雜度O(n^3log(n)),同樣注意去重複。

代碼:

class Solution {
public:
    vector<vector<int> > fourSum(vector<int> &num, int target) {
        int len=num.size();
        vector<vector<int> > res;
        if(len<4) return res;
        
        sort(num.begin(),num.end());
        
        for(int k=0;k<len-3;){
            for(int n=k+1;n<len-2;){
                int t=target-num[k]-num[n];
                for(int i=n+1,j=len-1;i<j;){
                    int tar=num[i]+num[j];
                    if(tar==t){//注意這裏比較的是 tar和t,不是原來的target了!
                        vector<int> one;
                        one.push_back(num[k]);
                        one.push_back(num[n]);
                        one.push_back(num[i]);
                        one.push_back(num[j]);
                        
                        res.push_back(one);
                        i++;j--;
                        while(i<j && num[i]==num[i-1]) i++;
                        while(j>i && num[j]==num[j+1]) j--;
                        
                    }else if(tar<t){//同t
                        i++;
                    }else{
                        j--;
                    }
                }// for i j
                n++;
                while(n<len-2 && num[n]==num[n-1]) n++;
            }//for n
            k++;
            while(k<len-3 && num[k]==num[k-1]) k++;
        }//for k
        return res;
    }
};
N Sum問題的思路懂了還是比較清晰的,可每次代碼都有點小問題。。。要嚴謹

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