代码随想录刷题第7天

今天内容依然是哈希方法。第一题是四数相加https://leetcode.cn/problems/4sum-ii/description/,直接的想法是4重循环,时间复杂度爆表,放弃。找卡哥代码随想录。使用的数据容器是unordered_map,分别对两个数组中的数值进行检索。

class Solution {
public:
    int fourSumCount(vector& nums1, vector& nums2, vector& nums3, vector& nums4) {
    unordered_map mymap;
    for(int a : nums1){
        for(int b : nums2){
            mymap[a + b]++;
        }
    }
    int result = 0;
    for(int c : nums3){
        for(int d : nums4){
            int targe = -(c + d);
            if(mymap.find(targe) != mymap.end()){
             result += mymap[targe];
            }
        }
    }
    return result;
    }
};

第二题是赎金信https://leetcode.cn/problems/ransom-note/description/,很奇怪的名字,感觉和做过的字母异位是一个壳子。直接用数组解了,先记录magazine中的元素出现情况,在记录信中的出现情况,只要信中元素出现次数多,返回false。代码很简单,编译一遍过了。

class Solution {
public:
    bool canConstruct(string ransomNote, string magazine) {
    int a[26] = {0};
    for(int i = 0; i < magazine.length(); i++){
        a[magazine[i] - 'a']++;
    }
    for(int j = 0; j < ransomNote.length(); j++){
        a[ransomNote[j] - 'a']--;
    }
    for(int b = 0; b < 26; b++){
        if(a[b] < 0) return false;
    }
    return true;
    }
};

第三题是三数之和https://leetcode.cn/problems/3sum/description/,感觉用哈希法有点麻烦,尝试直接遍历。问题出在如何把遍历到的结果填充到vector中,查阅资料发现是使用push_back,结果错误,未去重。

class Solution {
public:
    vector> threeSum(vector& nums) {
        vector> result;
        int count = 0;
       for(int i = 0; i < nums.size() - 2; i++){
           for(int j = i + 1; j < nums.size() - 1; j++){
               for(int k = j + 1; k < nums.size(); k++){
                   if(nums[i] + nums[j] + nums[k] == 0){
                    count++;
                    result.push_back(vector{nums[i], nums[j], nums[k]});
                   }
               }
           }
       } 
       return result;
    }
};

求助卡哥代码随想录,卡哥给出了两个思路,哈希与双指针,做了一些双指针的题,感到这种方法属实不太好想。哈希法也很麻烦,去重的主要问题在于数组的排序,跟着卡哥写了一版哈希法的代码,确实不容易。

class Solution {
public:
    vector> threeSum(vector& nums) {
        vector> result;
        sort(nums.begin(), nums.end());//排序我没想到
        for(int i = 0; i < nums.size(); i++){
            if (nums[i] > 0) break;
            if (i > 0 && nums[i] == nums[i - 1]) continue;
            unordered_set set;
            for(int j = i + 1; j < nums.size(); j++){
                if (j > i + 2 && nums[j] == nums[j-1] && nums[j-1] == nums[j-2]) continue;
                int c = -(nums[i] + nums[j]);
                if(set.find(c) != set.end()){
                    result.push_back({nums[i], nums[j], c});
                    set.erase(c);
                }
                else set.insert(nums[j]);
            }
        }
        return result;
    }
};

下面就是双指针法,核心问题也在去重逻辑的把握上。

class Solution {
public:
    vector> threeSum(vector& nums) {
        vector> result;
        sort(nums.begin(), nums.end());//去重的前提
        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 (right > left){
                if (nums[i] + nums[left] + nums[right] > 0) right--;
                else if(nums[i] + nums[left] + nums[right] < 0) left++;
                else {
                    result.push_back(vector{nums[i], nums[left], nums[right]});
                    while(right > left && nums[right] == nums[right - 1]) right--;
                    while(right > left && nums[left] == nums[left + 1]) left++;//对left、right去重
                    right--;left++;
                }
            } 
        }
        return result;
    }
};

第四题是四数之和https://leetcode.cn/problems/4sum/description/,和上一题很相似,但还是不会求助卡哥代码随想录,思路和三数之和一致,不过外层还要套一个for循环。

class Solution {
public:
    vector> fourSum(vector& nums, int target) {
    vector> result;
    sort(nums.begin(), nums.end());
    for (int k = 0; k < nums.size(); k++){
        if(nums[k] > target && nums[k] >= 0 && target >= 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 && target >= 0) break;
            if (i > k + 1 && nums[i] == nums[i - 1]) continue;
            int left = i + 1;
            int right = nums.size() - 1;
            while(right > left){
                if((long) nums[k] + nums[i] + nums[left] + nums[right] > target) right--;
                else if((long) nums[k] + nums[i] + nums[left] + nums[right] < target) left++;
                else {result.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 result;
    }
};

有史以来写过最长的代码。

那么哈希方法章节今天就结束了,我个人感觉哈希方法的应用面比较有针对性,判断元素是否在集合中,以后遇到此类题要往这方面想,同时做了一类的n数之和,再次巩固了双指针法的使用。此外也学到了数组,set,map作为哈希表的应用,本节的知识密度还是很大的。

你可能感兴趣的:(leetcode,算法,职场和发展)