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

454. 四数相加 II

看到本题想到如何使用哈希表的方法来解决,有两种计算方法,一种是求三个数组的和,然后用剩下的数的负数去使用哈希查询,但是这种方法的计算复杂度为O(n^3),还有一种就是两两求和,然后看其是否互补。

出现错误

直接使用unorder_set,没有考虑两个数相加后重复的情况。

class Solution {
public:
    int fourSumCount(vector& nums1, vector& nums2, vector& nums3, vector& nums4) {
        unordered_map umap;
        stack vec;
        int res{0};
        for(int i=0;i::iterator it=umap.find(-nums1[i]-nums2[j]);
                if(it==umap.end())umap.insert(pair(-nums1[i]-nums2[j],1));
                else it->second++;
            }
        }
        for(int i=0;i::iterator it=umap.find(nums3[i]+nums4[j]);
                if(it!=umap.end()){
                    res+=it->second;;
                }
            }
        }
        return res;
    }
};

383. 赎金信

本题和前面的242有效字符异位词思想类似。

class Solution {
public:
    bool canConstruct(string ransomNote, string magazine) {
        int a[26]={0};
        for(int i=0;i

15. 三数之和

使用双指针的方法能够比较好的完成本题。为了便于后续操作,首先将整个数组进行排序。首先定义一个下标,由于数组是从小到大的,如果第一个元素大于0,没有接下去的必要了,然后再下标+1的位置为left指针,数组最后为right指针,如果 nums[i]+nums[left]+nums[right]<0,则需要将left往右移,如果nums[i]+nums[left]+nums[right]>0,需要将right往左移。等于0则保存结果,在保存结果的时候需要注意,需要进行去重的操作,如果right和right-1相等,那么结果还是一样的,可以先将right--,同理,left如果和left+1相等,也需要进行去重的操作,由于需要循环需要保证left与right的大小关系,要加上限制条件right。由于i已经操作过了,如果i的值和i-1相等则不需要再进行了(注意是i-1而不是和i+1比,例如数组-1,-1,2,如果和i+1比会直接把这种情况删除了)。

出现错误

在对left与right进行去重操作时,为加入限制条件,容易导致越界的问题

class Solution {
public:
    vector> threeSum(vector& nums) {
        vector> res;
        sort(nums.begin(),nums.end());
        for(int i=0;i 0) {
                return res;
            }
              if (i > 0 && nums[i] == nums[i - 1]) {
                continue;
            }
            int left=i+1,right=nums.size()-1;
           while(left0)right--;
               else{
                    res.push_back(vector{nums[i], nums[left], nums[right]});
                    // 去重逻辑应该放在找到一个三元组之后,对b 和 c去重
                    while (right > left && nums[right] == nums[right - 1]) right--;
                    while (right > left && nums[left] == nums[left + 1]) left++;

                    // 找到答案时,双指针同时收缩
                    right--;
                    left++;
               }
           }
        }
        return res;
    }
};

   18. 四数之和

 本题可以延续上一题双指针的思想,本题的不同之处在于,题目的四数之和为target,如果target为负数时,不能说num[k]>target变剪枝,然后可以对里面的i进行二重剪枝。

出现错误

未加入(long)从而导致溢出

class Solution {
public:
    vector> fourSum(vector& nums, int target) {
        vector> res;
        sort(nums.begin(), nums.end());
        for(int k=0;k target && nums[k] >= 0)break;
            if(k>0&&nums[k]==nums[k-1])continue;
            for(int i=k+1;itarget&&nums[k] + nums[i] >= 0)break;
                // 对nums[i]去重
                if (i > k + 1 && nums[i] == nums[i - 1]) continue;
                int left=i+1;
                int right=nums.size()-1;
                while(lefttarget)right--;
                    else{
                        res.push_back(vector{nums[k],nums[i],nums[left],nums[right]});
                        while(right > left &&nums[right]==nums[right-1])right--;
                        while(right > left &&nums[left]==nums[left+1])left++;
                        right--;
                        left++;
                    }
                }
            }
        }
        return res;
    }
};

你可能感兴趣的:(代码随想录训练营,算法,散列表,数据结构)