代码随想录算法训练营第七天|454 四数相加II 383 赎金信 15 三数之和 18 四数之和

454 四数相加II

思路

哈希法以空间换时间提高效率

代码

class Solution {
public:
    int fourSumCount(vector<int>& nums1, vector<int>& nums2, vector<int>& nums3, vector<int>& nums4) {
        int result = 0;
        unordered_map<int,int> mp;
        for (auto n1 : nums1) {
            for(auto n2 : nums2) {
                int sum = n1 + n2;
                if(mp.find(sum) != mp.end()) {
                    mp[sum] ++;
                }
                else {
                    mp.insert({sum,1});
                }
            }
        }
        for (auto n3 : nums3) {
            for (auto n4 : nums4) {
                int sum2 = 0 - (n3 + n4);
                if (mp.find(sum2) != mp.end()) {
                    result += mp[sum2];
                }
            }
        }
        return result;
    }
};

总结

383 赎金信

思路

和字母异位词一样,但是我下意识用的是map,实际上用数组复杂度会更小

代码

class Solution {
public:
    bool canConstruct(string ransomNote, string magazine) {
        unordered_map<char,int> mp_mage;
        for (auto c : magazine) {
            if (mp_mage.find(c) != mp_mage.end()) {
                mp_mage[c] ++;
            }
            else {
                mp_mage.insert({c,1});
            }
        }
        for (auto c : ransomNote) {
            if (mp_mage.find(c) == mp_mage.end() || mp_mage[c] <= 0) {
                return false;
            }
            else {
                mp_mage[c] --;
            }
        }
        return true;
    }
};

总结

  1. 字符类型的哈希首先考虑是不是可以用数组(要考虑字母大小写)

15 三数之和

思路

N数之和
这题要求的结果中不能有重复的三元组,如果用Hash会比较耗时,所以用双指针

代码

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        sort(nums.begin(),nums.end());
        vector <vector <int>> result;
        
        for (int i = 0; i < nums.size() ; i++) {
            if (nums[i] > 0) {
                return result;
            }
            if (i>0 && nums[i] == nums[i-1]) {
                continue;
            }

            int left = i + 1;
            int right = nums.size() - 1;
            while (left < right) {
                int sum = nums[i] + nums[left] + nums[right];
                if (sum < 0) {
                    
                        left ++;
                    
                }
                else if (sum > 0) {
                    
                        right --;
                    
                }
                else if (sum == 0) {
                    vector<int> res = {nums[i],nums[left],nums[right]};
                    result.push_back(res);
                    while (left < right && nums[left] == nums[left+1]) {
                        left ++;
                    }
                    while (left < right && nums[right] == nums[right-1]) {
                        right --;
                    }
                    
                    left ++;
                    right --;
                }
            }
        }
        return result;
    }
};

总结

  1. 去重思路
  2. 双指针方法需要先排序
  3. 这题要求的是元素组成的三元组,所以可以排序,如果是要求返回元素下标,就不可以排序了

18 四数之和

思路

延续三数之和思路

代码

class Solution {
public:
    vector<vector<int>> fourSum(vector<int>& nums, int target) {
        
        vector<vector<int>> result;
        sort(nums.begin(),nums.end());

        for (int k = 0; k < nums.size(); k++) {
            if (nums[k] > target  && nums[k] >= 0 ) {
                    break;
                }
            if ( k > 0 && nums[k] == nums[k-1]) {
                continue;
            }
            for (int i = k + 1; i < nums.size(); i++) {
                if (nums[k] + nums[i] > target  && nums[k] + nums[i]>= 0 ) {
                    break;
                }
                if (i > k + 1 && nums[i] == nums[i-1]){
                    continue;
                }
                int left = i + 1;
                int right = nums.size() - 1;
                
                while (left < right) {
                    // long sum = nums[k] + nums[i] + nums[left] + nums[right];
                    // if (sum < target) {
                    //     left++;
                    // }
                    // else if (sum > target) {
                    //     right --;
                    // }
                    // else {
                    //     vector<int> res = {nums[k],nums[i],nums[left],nums[right]};
                    //     result.push_back(res);
                        
                    //     while(left<right && nums[right] == nums[right-1]) {
                    //         right --;
                    //     }
                    //     while(left<right && nums[left] == nums[left+1]) {
                    //         left ++;
                    //     }
                    //     left ++;
                    //     right --;
                    // }
                    
                    if ((long)nums[k] + nums[i] + nums[left] + nums[right] < target) {
                        left++;
                    }
                    else if ((long)nums[k] + nums[i] + nums[left] + nums[right] > target) {
                        right --;
                    }
                    else {
                        vector<int> res = {nums[k],nums[i],nums[left],nums[right]};
                        result.push_back(res);
                        
                        while(left<right && nums[right] == nums[right-1]) {
                            right --;
                        }
                        while(left<right && nums[left] == nums[left+1]) {
                            left ++;
                        }
                        left ++;
                        right --;
                    }
                }
            }
        }
        return result;
    }
};

总结

双指针法将时间复杂度:O(n^2)的解法优化为 O(n)的解法。也就是降一个数量级,题目如下:
27.移除元素
15.三数之和
18.四数之和

链表相关双指针题目:
206.反转链表
19.删除链表的倒数第N个节点
面试题 02.07. 链表相交
142题.环形链表II

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值