1. 程式人生 > >(1 / 15 / 16 / 18) NSum問題集合

(1 / 15 / 16 / 18) NSum問題集合

總接受:245851總提交:1014135困難:容易

給定一個整數陣列,返回兩個數的下標位置,他們加起來是一個指定目標值。

你應該認為每個輸入恰有一個解決方案。

例子:

 
給定num =(2、7、11、15),目標值= 9,

因為num[0]+ num[1]= 2 + 7 = 9,
所以返回[0,1]。

更新(2016/2/13):
返回的格式已經改變了從零開始的索引。請仔細閱讀上述更新描述。

分析:DONE

其實比較簡單的解法是在遍歷陣列時,總是在每個元素後面的所有元素中,即[i+1,n)的範圍內尋找target-nums[i]這個值,如果存在這個值則返回下標i個這個值的下標即可。時間浮渣度為O(n^2),空間複雜度為O(1)。

但是,比較顯然的是可以用雜湊map來加速查詢(因為他是常數時間的查詢),此時可以往前找也可以往後搜尋目的值,方案如下:

一直遍歷陣列

1)在雜湊map中尋找target-nums[i]

2)如果存在則返回這對下標,否則壓入nums[i]到雜湊map中

空間複雜度為O(N),時間浮渣度為O(N),通過所有測試案例耗時16ms

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        //於2016.6.10徒手重寫
        map<int,int> mapping;
        vector<int> result;
        for(int i=0;i<nums.size();i++)
        {
            if(mapping.find(target-nums[i])!=mapping.end() )
            {
                result.push_back(mapping[target-nums[i]]);
                result.push_back(i);
                return result;
            }
            mapping[nums[i]]=i;
        }
        return result;
    }
};

15. 3Sum

Total Accepted: 102450 Total Submissions: 560117 Difficulty: Medium

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:

  • Elements in a triplet (a,b,c) must be in non-descending order. (ie, a
     ≤ b ≤ c)
  • 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)

分析:

暴力破解,時間複雜度是O(n^3),超時

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        vector<vector<int>> result;
        if(nums.size()<=2)
            return result;  
        int pos1=0,pos2=0,pos3=0;
        for(;pos1<nums.size();pos1++)
        {
            pos2=pos1+1;
            for(;pos2<nums.size();pos2++)
            {
                pos3=pos2+1;
                for(;pos3<nums.size();pos3++)
                {
                    if((nums[pos1]+nums[pos2]+nums[pos3])==0)
                    {
                        vector<int> tmpres;
                        tmpres.push_back(nums[pos1]);
                        tmpres.push_back(nums[pos2]);
                        tmpres.push_back(nums[pos3]);
                        sort(tmpres.begin(),tmpres.end()); 
                        result.push_back(tmpres);
                    }
                }
            }
        }
        
        return result;
    }
};

別人的做法:

本體只需要找到三個數相加=0,那麼只需要在遍歷陣列元素時,另外兩個加起來等於負的當前元素即可。

然後利用雙指標查詢這樣的兩個元素。

關鍵詞:先排序,再遍歷,雙指標,防重複操作。

class Solution {
public:
    vector<vector<int> > threeSum(vector<int> &num) {
        int n = num.size();
        sort(num.begin(), num.end());//排序
        vector<vector<int> > res;
        for(int i = 0; i < n-2; i++)
        {
            if(i > 0 && num[i] == num[i-1])
                continue;//重複的元素不用計算
            int target = num[i];
            twoSum(num, i+1, -target, res);//從當前元素後面開始找相加為目標值(當前元素的負值)的兩個數字
        }
        return res;
    }
    void twoSum(vector<int> &sortedNum, int start, int target, vector<vector<int> >&res)
    {
        int head = start, tail = sortedNum.size() - 1;
        while(head < tail)
        {
            int tmp = sortedNum[head] + sortedNum[tail];
            if(tmp < target)
                head++;
            else if(tmp > target)
                tail--;
            else//相等,獲取結果
            {
                res.push_back(vector<int>{sortedNum[start-1], sortedNum[head], sortedNum[tail]});
                //為了防止出現重複結果,跳過相等的情況
                int k = head+1;
                while(k < tail && sortedNum[k] == sortedNum[head])
                    k++;
                head = k;
                
                k = tail-1;
                while(k > head && sortedNum[k] == sortedNum[tail])
                    k--;
                tail = k;
            }
        }
    }
};




16. 3Sum Closest

   My Submissions Total Accepted: 76863 Total Submissions: 263989 Difficulty: Medium

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).

分析:

a+b+c儘可能接近target,那麼如前面一題所示,當遍歷到元素a時,

我們在其後尋找b和c之和接近target-a的兩個數即可。而儘可能接近的標準就是兩者之差儘可能小。

基於上面一題的提示,這個題就簡單很多了,如程式碼所示:

class Solution {
public:
    int threeSumClosest(vector<int>& num, int target) {
        int n = num.size();  
        sort(num.begin(), num.end());//排序  
        int result=0, min_gap=INT_MAX;  
        for(int i = 0; i < n-2; i++)  
        {  
            if(i > 0 && num[i] == num[i-1])  
                continue;//重複的元素不用計算  
            int tmptarget =target - num[i];
            if(twoSum(num, i+1, tmptarget, result,min_gap)) //從當前元素後面開始找相加接近目標值的兩個數字之和  
                break;
        }  
        return result;  
    }
    bool twoSum(vector<int> &sortedNum, int start, int tmptarget, int &result,int &min_gap)  
    {  
        int head = start, tail = sortedNum.size() - 1;  
        
        while(head < tail)  
        {  
            int tmp = sortedNum[head] + sortedNum[tail];  //tmp要儘可能接近tmptarget,甚至相等
            if(tmp < tmptarget)  
            {   
                if(min_gap > abs(tmptarget-tmp))
                {
                    min_gap=abs(tmptarget-tmp);
                    result=sortedNum[start-1]+ sortedNum[head]+ sortedNum[tail];
                }
                head++;  
            }
            else if(tmp > tmptarget)  
            {
                if(min_gap > abs(tmptarget-tmp))
                {
                    min_gap=abs(tmptarget-tmp);
                    result=sortedNum[start-1]+ sortedNum[head]+ sortedNum[tail];
                }
                tail--;  
            }
            else//相等,相差距離絕對最短,直接獲取結果退出即可。
            {  
                result=sortedNum[start-1]+ sortedNum[head]+ sortedNum[tail];
                return true;
            }  
        }  
        return false;
    }  
};


18. 4Sum

  Total Accepted: 71829 Total Submissions: 301721 Difficulty: Medium

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:

  • Elements in a quadruplet (a,b,c,d) must be in non-descending order. (ie, a ≤ b ≤ c ≤ d)
  • 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)

分析:

與前面的題類似,不在累述!

class Solution {
public:
    vector<vector<int>> fourSum(vector<int>& num, int target) {
        int n = num.size();    
        if(n < 4)
            return result;
        sort(num.begin(), num.end());//排序    
        for(int i = 0; i < n-3; i++)    
        {    
            for(int j=i+1;j<n-2;j++)
            {
                int tmptarget =target - num[i]-num[j];  
                twoSum(i,num, j+1, tmptarget);//從當前元素後面開始找相加接近目標值的兩個數字之和   
                while(j < n-2&&num[j+1]==num[j])//防重複答案
                    j++;
            }
             while(i < n-3 && num[i+1]==num[i])//防重複答案
                    i++;
        }    
        return result;
    }
    
    void twoSum(int i,vector<int> &sortedNum, int start, int target)  
    {  
        int head = start, tail = sortedNum.size() - 1;  
        while(head < tail)  
        {  
            int tmp = sortedNum[head] + sortedNum[tail];  
            if(tmp < target)  
                head++;  
            else if(tmp > target)  
                tail--;  
            else//相等,獲取結果  
            {  
                result.push_back(vector<int>{sortedNum[i],sortedNum[start-1], sortedNum[head], sortedNum[tail]});  
                //為了防止出現重複結果,跳過相等的情況  
                int k = head+1;  
                while(k < tail && sortedNum[k] == sortedNum[head])  
                    k++;  
                head = k;  
                  
                k = tail-1;  
                while(k > head && sortedNum[k] == sortedNum[tail])  
                    k--;  
                tail = k;  
            }  
        }  
    }  
private:
    vector<vector<int>> result;
};


注:本博文為EbowTang原創,後續可能繼續更新本文。如果轉載,請務必複製本條資訊!

原文地址:http://blog.csdn.net/ebowtang/article/details/50320391

原作者部落格:http://blog.csdn.net/ebowtang

本部落格LeetCode題解索引:http://blog.csdn.net/ebowtang/article/details/50668895