leetcode 1.Two Sum 、167. Two Sum II - Input array is sorted 、15. 3Sum 、16. 3Sum Closest 、 18. 4Su...

 1.two sum

用hash来存储数值和对应的位置索引,通过target-当前值来获得需要的值,然后再hash中寻找

错误代码1:

Input:
[3,2,4]
6
Output:
[0,0]
Expected:
[1,2]

同一个数字不能重复使用,但这个代码没排除这个问题

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        vector<int> result;
        unordered_map<int,int> m;
        for(int i = 0;i < nums.size();i++)
            m[nums[i]] = i;
        for(int i = 0;i < nums.size();i++){
            int num = target - nums[i];
            if(m.count(num)){
                result.push_back(i);
                result.push_back(m[num]);
                break;
            }
        }
        return result;
    }
};

错误代码2:

Input:
[3,3]
6
Output:
[]
Expected:
[0,1]

可以使用相同的数字,但不能使用同一位置的数字,这个错误代码实际上是针对相同数字,而不是同一位置的数字

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        vector<int> result;
        unordered_map<int,int> m;
        for(int i = 0;i < nums.size();i++)
            m[nums[i]] = i;
        for(int i = 0;i < nums.size();i++){
            int num = target - nums[i];
            if(m.count(num) && num != nums[i]){
                result.push_back(i);
                result.push_back(m[num]);
                break;
            }
        }
        return result;
    }
};

正确代码:

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        vector<int> result;
        unordered_map<int,int> m;
        for(int i = 0;i < nums.size();i++)
            m[nums[i]] = i;
        for(int i = 0;i < nums.size();i++){
            int num = target - nums[i];
            if(m.count(num) && m[num] != i){
                result.push_back(i);
                result.push_back(m[num]);
                break;
            }
        }
        return result;
    }
};

说白了错误2是判断数值相等,正确的写法是判断索引是否相等,就直接拒绝了这种同一个数字重复两次的情况

167. Two Sum II

数组是有序的,所以用两个指针从两侧向中间滑动就可以解决

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

15. 3Sum 

先将数组排序,然后固定一个数,再将剩下两个数类似于two sumII的方法在数组开始和末尾进行滑动。

因为不求重复的,所以在滑动的过程中:1.在for循环中遇到相同的数字直接continue

                  2.在while循环中也是直接++或者--

                          3.另外如果当便利到的第一个数大于0了,那后面的数都会大于0,也就没有了计算的意义,所以可以直接break掉

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        vector<vector<int>> result;
        if(nums.size() < 3)
            return result;
        sort(nums.begin(),nums.end());
        for(int i = 0;i <= nums.size() - 3;i++){
            if(nums[i] > 0)
                break;
            if(i > 0 && nums[i] == nums[i-1])
                continue;
            int target = 0 - nums[i];
            int start = i + 1;
            int end = nums.size() - 1;
            while(start < end){
                int sum = nums[start] + nums[end];
                if(sum == target){
                    vector<int> res;
                    res.push_back(nums[i]);
                    res.push_back(nums[start]);
                    res.push_back(nums[end]);
                    result.push_back(res);
                    while(start < end && nums[start] == nums[start+1])
                        start++;
                    while(start < end && nums[end-1] == nums[end])
                        end--;
                    start++;
                    end--;
                }
                else if(sum < target)
                    start++;
                else
                    end--;
            }
        }
        return result;
    }
};

# 这个题必须有if(nums.size() < 3),不然在nums为[]时就会报错。
原因在于https://stackoverflow.com/questions/47947956/reference-binding-to-null-pointer-of-type-value-type
size()函数返回的是无符号的,0-3会得到一个很大的数

 

 

 16. 3Sum Closest

与3Sum类似的思路,先排序,然后固定其中一个值,再滑动另外两个值。3Sum相等时还需要继续移动start、end,但这个时候的比较是比较diff的最小值,滑动判断的条件是根据sum与target的值在判断

错误写法:

认为初始sum的时候计算了第一个位置,即index=0,for循环就从index=1开始,但实际上只计算了前三个,index=0还有很多其他的和的情况,比如index=0、index=1、index=3

class Solution {
public:
    int threeSumClosest(vector<int>& nums, int target) {
        sort(nums.begin(),nums.end());
        int sum = nums[0] + nums[1] + nums[2];
        int res = sum;
        int diff = abs(target - sum);
        for(int i = 1;i <= nums.size() - 3;i++){
            int start = i + 1;
            int end = nums.size() - 1;
            while(start < end){
                int sum = nums[i] + nums[start] + nums[end];
                int new_diff = abs(target - sum);
                if(new_diff < diff){
                    diff = new_diff;
                    res = sum;
                }
                if(sum < target)
                    start++;
                else
                    end--;
            }
        }
        return res;
    }
};

正确写法:

class Solution {
public:
    int threeSumClosest(vector<int>& nums, int target) {
        sort(nums.begin(),nums.end());
        int sum = nums[0] + nums[1] + nums[2];
        int res = sum;
        int diff = abs(target - sum);
        for(int i = 0;i <= nums.size() - 3;i++){
            int start = i + 1;
            int end = nums.size() - 1;
            while(start < end){
                int sum = nums[i] + nums[start] + nums[end];
                int new_diff = abs(target - sum);
                if(new_diff < diff){
                    diff = new_diff;
                    res = sum;
                }
                if(sum < target)
                    start++;
                else
                    end--;
            }
        }
        return res;
    }
};

  

18. 4Sum

这个题和3Sum很像,但3Sum的target是固定为0,4Sum是任意target。

两者都是先排序,3Sum是固定一个数,4Sum类似于固定两个数,即有两个数是外层for循环。两者都需要去重。

错误写法:

j > 1,这种情况就要报错:

Input:
[-1,0,1,2,-1,-4]
-1
Output:
[[-4,0,1,2]]
Expected:
[[-4,0,1,2],[-1,-1,0,1]]

j > 1这种写法会把之后所有的j > 1相同的都去掉,让后面的根本没有进行比较

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

正确写法:

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

 

 

 

653. Two Sum IV - Input is a BST 

只要是两数之和的题,一定要记得先尝试用Hash来做,这道题只不过是把数组变成了一棵二叉树而已,换汤不换药。

还是用递归的思想,遍历到每个节点的时候,用target-当前节点的值,看hash里面是否存储了值。如果没有就递归遍历,同时将此节点的值存储在hash中,以便后面的值去寻找。

class Solution {
public:
    bool findTarget(TreeNode* root, int k) {
        unordered_set<int> container;
        return findTarget(root,k,container);
    }
    bool findTarget(TreeNode* root,int k,unordered_set<int>& container){
        if(root == NULL)
            return false;
        int val = k - root->val;
        if(container.count(val))
            return true;
        container.insert(root->val);
        return findTarget(root->left,k,container) || findTarget(root->right,k,container);
    }
};

 

 

454. 4Sum II

https://www.cnblogs.com/grandyang/p/6073317.html

class Solution {
public:
    int fourSumCount(vector<int>& A, vector<int>& B, vector<int>& C, vector<int>& D) {
        unordered_map<int,int> m;
        for(int i = 0;i < A.size();i++){
            for(int j = 0;j < B.size();j++){
                m[A[i] + B[j]]++;
            }
        }
        int res = 0;
        for(int i = 0;i < C.size();i++){
            for(int j = 0;j < D.size();j++){
                int tmp = -(C[i] + D[j]);
                if(m.find(tmp) != m.end())
                    res += m[tmp];
            }
        }
        return res;
    }
};

 

转载于:https://www.cnblogs.com/ymjyqsx/p/9556628.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
给定一个整数数组 nums 和一个目标值 target,要求在数组中找出两个数的和等于目标值,并返回这两个数的索引。 思路1:暴力法 最简单的思路是使用两层循环遍历数组的所有组合,判断两个数的和是否等于目标值。如果等于目标值,则返回这两个数的索引。 此方法的时间复杂度为O(n^2),空间复杂度为O(1)。 思路2:哈希表 为了优化时间复杂度,可以使用哈希表来存储数组中的元素和对应的索引。遍历数组,对于每个元素nums[i],我们可以通过计算target - nums[i]的值,查找哈希表中是否存在这个差值。 如果存在,则说明找到了两个数的和等于目标值,返回它们的索引。如果不存在,将当前元素nums[i]和它的索引存入哈希表中。 此方法的时间复杂度为O(n),空间复杂度为O(n)。 思路3:双指针 如果数组已经排序,可以使用双指针的方法来求解。假设数组从小到大排序,定义左指针left指向数组的第一个元素,右指针right指向数组的最后一个元素。 如果当前两个指针指向的数的和等于目标值,则返回它们的索引。如果和小于目标值,则将左指针右移一位,使得和增大;如果和大于目标值,则将右指针左移一位,使得和减小。 继续移动指针,直到找到两个数的和等于目标值或者左指针超过了右指针。 此方法的时间复杂度为O(nlogn),空间复杂度为O(1)。 以上三种方法都可以解决问题,选择合适的方法取决于具体的应用场景和要求。如果数组规模较小并且不需要考虑额外的空间使用,则暴力法是最简单的方法。如果数组较大或者需要优化时间复杂度,则哈希表或双指针方法更合适。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值