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

#454四数相加II M 不会,好难,直接看思路+自己实现 30min,hash一般有思路了实现都挺快

 

!这个和后面同ary内三数四数之和的区别是,是在4个vec内,不用去重

分成 a+b c+d O(n^4)->O(n^2)

int fourSumCount(vector& nums1, vector& nums2, vector& nums3, vector& nums4) {
        unordered_map abmap;
        int cnt=0;
        for (auto &ele1:nums1){
            for (auto &ele2:nums2){
                abmap[ele1+ele2]+=1;
            }
        }

        for(auto & ele3:nums3){
            for (auto &ele4:nums4){
                if(abmap.find(0-ele3-ele4)!=abmap.end()){
                    cnt+=abmap[0-ele3-ele4];
                }

            }
        }
        return cnt;
        
    }

#383 赎金信 E 自己做很快

记得map中map[ ]--到0时要手动erase,不然后面find判断会出错

bool canConstruct(string ransomNote, string magazine) {
        unordered_map mmap;
        for(char &c:magazine){
            mmap[c]++;
        }

        for(char &c:ransomNote){
            if(mmap.find(c)!=mmap.end()){
                mmap[c]--;
                if(mmap[c]==0){
                    mmap.erase(c);
                }
            }
            else{
                return false;
            }
        }
        return true;
        
    }

但代码随想录用ary做hash更好!因为”本题情况下,使用map的空间消耗要比数组大一些的,因为map要维护红黑树或者哈希表,而且还要做哈希函数,是费时的!数据量大的话就能体现出来差别了。 所以数组更加简单直接有效!”可行的情况下hash用ary做是很好的

bool canConstruct(string ransomNote, string magazine) {
        int record[26] = {0};
        //add
        if (ransomNote.size() > magazine.size()) {
            return false;
        }
        for (int i = 0; i < magazine.length(); i++) {
            // 通过recode数据记录 magazine里各个字符出现次数
            record[magazine[i]-'a'] ++;
        }
        for (int j = 0; j < ransomNote.length(); j++) {
            // 遍历ransomNote,在record里对应的字符个数做--操作
            record[ransomNote[j]-'a']--;
            // 如果小于零说明ransomNote里出现的字符,magazine没有
            if(record[ransomNote[j]-'a'] < 0) {
                return false;
            }
        }
        return true;
    }

#15 3sum == 0 M 难而经典

关键:i left right 三个指针,i正常遍历,left,right根据sum情况不断变化

去重!i是nums[i]==nums[i-1]之后就会产生一样的tuple,right和left是路上的下一个如果遇到一样的就跳过;但是i是要用前一个比,而不是下一个,因为是可以 (-1,-1,2)这样的

关于两个去重while的条件,我觉得left

vector> threeSum(vector& nums) {
        sort(nums.begin(), nums.end());
        vector> res;
        int left,right;
        for(int i=0;i0){return res;}
            if(i>=1 && nums[i]==nums[i-1]){continue;}
            left=i+1;
            right=nums.size()-1;
            while(left0){right--;}
                else if(nums[i]+nums[left]+nums[right]<0){left++;}
                else{//==0
                    res.push_back({nums[i],nums[left],nums[right]});
                    //while(left= 0 && nums[right] == nums[right - 1]) { right--; }
                    while(left + 1 < nums.size() && nums[left] == nums[left + 1]) { left++; }
                    right--;
                    left++;
                }
            }
        }
        return res;

    }

#18 4sum == target M 难而经典,3sum基础上多考虑的东西:

k,i ,left,right 四个;target可能为正、负、0,剪枝(break/continue)条件只能用正的case

我看了思路自己实现错的地方:

1. i>k+1 那里开始写的不对,因为i=k+1,要在当前k循环中第二次看见某个数,必然i>k+1这个初始值

2.long那里老弄不对

long sum = (long)nums[k] + (long)nums[i] + (long)nums[left] + (long)nums[right]; 这是对的

long sum = (long) nums[k] + nums[i] + nums[left] + nums[right] 这也是对的

long sum = (long)(nums[k] + nums[i] + nums[left] + nums[right])但这是错的,因为后面那些int加起来已经溢出了

第二句对的原因:代码随想录算法训练营第7天 | 454.四数相加II 383. 赎金信 15. 三数之和 18. 四数之和_第1张图片

anyway有很大的数,很多的数相加一定要注意type只是int会不会溢出

vector> fourSum(vector& nums, int target) {
        sort(nums.begin(),nums.end());
        vector> res;
        int left,right;
        for (int k=0;k=target && nums[k]>0){break;}//>= > ???
            if(k>=1 && nums[k]==nums[k-1]){continue;}
            for (int i=k+1;i=target && nums[i]+nums[k]>0){break;}
                if(i > k+1 && nums[i]==nums[i-1]){continue;} //在当前k循环中第一次看到这数
                left=i+1;
                right=nums.size()-1;
                while(lefttarget){right--;}
                    else if(sum

你可能感兴趣的:(代码随想录一刷,算法,哈希算法,c++,数据结构)