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


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值