LeetCode|*Sum


本文地址

Two Sum

Two 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].
哈希表:
O(n)的时间和空间复杂度
注意样例:
【0, 4, 3, 0】
0

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        unordered_map<int, int> um;// val2index
        vector<int> res;
        for(int i = 0; i < nums.size(); i++){
            int complement = target-nums[i];
            unordered_map<int, int>::iterator it = um.find(complement);
            if(it != um.end() ){
                res.push_back(it->second);
                res.push_back(i);
                return res;
            } else{
                um[nums[i]] = i;
            }
        } return vector<int>(); // not find
    }
};

Two Sum II - Input array is sorted

题目链接 Two Sum II - Input array is sorted

Given an array of integers that is already sorted in ascending order, 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.

Note:

Your returned answers (both index1 and index2) are not zero-based.
You may assume that each input would have exactly one solution and you may not use the same element twice.
Example:

Input: numbers = [2,7,11,15], target = 9
Output: [1,2]
Explanation: The sum of 2 and 7 is 9. Therefore index1 = 1, index2 = 2.

下面的代码是O(n)的复杂度,《剑指offer》上也有这道题

class Solution {
public:
    vector<int> twoSum(vector<int>& numbers, int target) {
        vector<int> res;
        if(numbers.size() == 0) return res;
        int i = 0, j = numbers.size()-1;
        while(i < j){            
            if(numbers[i] + numbers[j] == target){
                res.push_back(i+1);
                res.push_back(j+1);
                return res;
            } 
            if(numbers[i] + numbers[j] < target) ++i;
            else --j;
        } return res;
    }
};

Two Sum IV - Input is a BST

Two Sum IV - Input is a BST
Given a Binary Search Tree and a target number, return true if there exist two elements in the BST such that their sum is equal to the given target.

Example 1:

Input: 
    5
   / \
  3   6
 / \   \
2   4   7
Target = 9
Output: True

Example 2:

Input: 
    5
   / \
  3   6
 / \   \
2   4   7
Target = 28
Output: False

推荐题解 链接, 这里讲了3种方法来做这道题
方法一:哈希表记录每个节点的值,时间复杂度O(n), 空间复杂度O(n)。遍历树的方法可以是preorder,inorder 或者 postorder

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    bool findTarget(TreeNode* root, int k) {
        s = unordered_set<int>();
        return helper(root, k);
    }
    bool helper(TreeNode* root, int k){
        if(root == NULL) return false;
        if(helper(root->left, k)) return true;
        if(s.find(k - root->val) != s.end()) return true;
        s.insert(root->val);
        return helper(root->right, k);
    }
private:
    unordered_set<int> s;
};

方法2: 利用中序遍历把tree保存在一个数组中,此时得到有序的数组。然后用two sum的方法即可。时间复杂度O(n), 空间复杂度O(n)。

class Solution {
public:
    bool findTarget(TreeNode* root, int k) {
        v = vector<int>();
        helper(root);
        int l = 0, r = v.size()-1;
        while(l < r){
            if(v[l]+v[r] == k) return true;
            if(v[l]+v[r] < k) ++l;
            else --r;
        } return false;
    }
    void helper(TreeNode* root){
        if(root == NULL) return;
        helper(root->left);
        v.push_back(root->val);
        helper(root->right);
    }
private:
    vector<int> v;
};

方法3:
节点个数为n, 树高为h. 那么我们可以对每个节点的值val搜索 k-val是否在tree中。
时间复杂度O(nh).

class Solution {
public:
    bool findTarget(TreeNode* root, int k) {
        if(root == NULL) return false;
        return dfs(root, root, k);
    }
private:    
    bool dfs(TreeNode* root, TreeNode* cur, int k){
        /* root一直为tree的根节点.
           当前选择到的节点为cur
           2sum目标为k */
        if(cur == NULL) return false;
        return search(root, cur, k - cur->val) 
            || dfs(root, cur->left, k)
            || dfs(root, cur->right, k);
    }
    bool search(TreeNode* root, TreeNode* cur, int val){
        /* 当前选择的节点为cur, 需要搜到的节点值为val.  初试root为tree的根节点 */
        if(root == NULL) return false;
        return ((root->val == val) && (root != cur))
            || ((root->val < val) && search(root->right, cur, val))
            || ((root->val > val) && search(root->left, cur, val));
    }
    
};

3Sum

3Sum

Given an array nums of n integers, are there elements a, b, c in nums 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.

Example:

Given array nums = [-1, 0, 1, 2, -1, -4],

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

先选择一个数,然后问题转变为2sum。时间复杂度为 O ( n 2 ) O(n^2) O(n2)

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        vector<vector<int> > res;
        if(nums.size() == 0) return res;
        sort(nums.begin(), nums.end());
        for(int i = 0; i < nums.size(); ++i){
            if(i > 0 && nums[i-1] == nums[i]) continue;  // nums[i] 不能重复选择
            int sum = -nums[i];
            int l = i+1, r = nums.size()-1;
            while(l < r){
                if(nums[l] + nums[r] == sum){
                    vector<int> v;
                    v.push_back(nums[i]);
                    v.push_back(nums[l]);
                    v.push_back(nums[r]);
                    res.push_back(v);
                    while(l+1 < r && nums[l] == nums[l+1]) ++l;  // nums[l] 不能重复选择
                    ++l;
                    while(l < r-1 && nums[r-1] == nums[r]) --r;  // nums[r] 不能重复选择
                    --r;
                } else if(nums[l] + nums[r] < sum){
                    ++l;
                } else{
                    --r;
                }
            }
        } return res;
    }
};

3Sum Closest

题目链接3Sum Closest
Given an array nums of n integers and an integer target, find three integers in nums such that the sum is closest to target. Return the sum of the three integers. You may assume that each input would have exactly one solution.

Example:

Given array nums = [-1, 2, 1, -4], and target = 1.

The sum that is closest to the target is 2. (-1 + 2 + 1 = 2).

class Solution {
public:
    int threeSumClosest(vector<int>& nums, int target) {
        int res = 0; // assert(nums.size() >= 3)
        if(nums.size() == 0) return res;
        sort(nums.begin(), nums.end());
        unsigned int diff = UINT_MAX;
        for(int i = 0; i < nums.size(); ++i){
            if(i > 0 && nums[i-1] == nums[i]) continue;
            int sum = target - nums[i], l = i+1, r = nums.size()-1;
            while(l < r){
                int cur = nums[l] + nums[r];
                if(cur == sum) return target;
                unsigned int ndiff = abs(sum-cur);
                if(ndiff < diff){
                    res = nums[i] + cur;
                    diff = ndiff;
                }
                if(cur < sum) ++l;
                else --r;
                
            }
        } return res;
        
    }
};

4Sum

4Sum

4sum转化为2sum问题,间复杂度为 O ( n 3 ) O(n^3) O(n3)

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

4Sum II

4Sum II
Given four lists A, B, C, D of integer values, compute how many tuples (i, j, k, l) there are such that A[i] + B[j] + C[k] + D[l] is zero.

To make problem a bit easier, all A, B, C, D have same length of N where 0 ≤ N ≤ 500. All integers are in the range of -228 to 228 - 1 and the result is guaranteed to be at most 231 - 1.

Example:

Input:
A = [ 1, 2]
B = [-2,-1]
C = [-1, 2]
D = [ 0, 2]

Output:
2

Explanation:
The two tuples are:
1. (0, 0, 0, 1) -> A[0] + B[0] + C[0] + D[1] = 1 + (-2) + (-1) + 2 = 0
2. (1, 1, 0, 0) -> A[1] + B[1] + C[0] + D[0] = 2 + (-1) + (-1) + 0 = 0

Time complexity: O(n^2)
Space complexity: O(n^2)

class Solution {
public:
    int fourSumCount(vector<int>& A, vector<int>& B, vector<int>& C, vector<int>& D) {
        m = unordered_map<long long, int>();
        int res = 0;
        for(auto a: A){
            for(auto b: B){
                ++m[a+b];
            }
        }
        for(auto c: C){
            for(auto d: D){
                res += m[-c-d];
            }
        } return res;
    }
private:
    unordered_map<long long, int> m;
};

k Sum (TBD)

k Sum

Description1
Given n distinct positive integers, integer k (k <= n) and a number target.
Find k numbers where sum is target. Calculate how many solutions there are?

Example

	Given [1,2,3,4], k = 2, target = 5.
	There are 2 solutions: [1,4] and [2,3].
	Return 2.
class Solution {
public:
    /**
     * @param A: An integer array
     * @param k: A positive integer (k <= length(A))
     * @param target: An integer
     * @return: An integera
     */
    int kSum(vector<int> &A, int k, int target) {
        res = 0;
        if(k < 1 || A.size() < k) return res;
        if(k == 1){
            for(int a: A) if(a == target) ++res;
            return res;
        }
        sort(A.begin(), A.end());
        helper(A, k, 0, A.size()-1, target);
        return res;
    }

private:
    int res;
    void helper(vector<int>& A, int k, int s, int e, int target){
        if(k == 2){
            while(s < e){
                if(A[s] + A[e] == target){
                    ++res;
                    while(s+1 < e && A[s] == A[s+1]) ++s;
                    ++s;
                    while(s < e-1 && A[e-1] == A[e]) --e;
                    --e;
                } else if(A[s] + A[e] < target) ++s;
                else --e;
            }
        } else{
            /*
            int minv = 0, maxv = 0;
            for(int j = 0; j < k; ++j){
                minv += A[s+j];
                maxv += A[e-j];
            } if(minv > target || maxv < target) return; */
            for(int i = s; i <= e-k+1; ++i){
                int minv = 0, maxv = 0;  // 可以起到一定的优化作用
                for(int j = 0; j < k; ++j){
                    minv += A[i+j];
                    maxv += A[e-j];
                } if(minv > target || maxv < target) return;
                if(i > s && A[i-1] == A[i]) continue;
                helper(A, k-1, i+1, e, target-A[i]);
            }
        }
    }
};

样例超时过不了

Input
[1,4,6,9,10,13,14,17,19,22,25,28,30,33,36,37,38,41,42,45,47,49,51,54,57,58,59,62,64,67,69,71,73,74,77]
23
1000
Expected
2485463

此题应该使用dp来做。

参考资料

http://www.cnblogs.com/tenosdoit/p/3649607.html O(n^2)的算法求解4-sum
https://blog.csdn.net/qq_20404903/article/details/80928130 K-sum
https://www.lintcode.com/problem/k-sum/description k-sum的OJ题目

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值