<LeetCode OJ> (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

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值