「程式碼隨想錄演算法訓練營」第五天 | 雜湊表 part1

云雀AC了一整天發表於2024-07-08

242. 有效的字母異位詞

題目連結:https://leetcode.cn/problems/valid-anagram/
題目難度:簡單
文章講解:https://programmercarl.com/0242.有效的字母異位詞.html
影片講解: https://www.bilibili.com/video/BV1YG411p7BA
題目狀態:一次過,哈哈哈

個人思路:

之前在《劍指offer》中做過這個題目,思路就是直接建立兩個26位的陣列,分別存放兩個字串中出現的小寫字母的個數,若最後這兩個陣列相等,則表示這兩個字串互為字母異位詞。

實現程式碼:

class Solution {
public:
    bool isAnagram(string s, string t) {
        int sLen = s.size();
        int tLen = t.size();
        if(sLen != tLen) return false;

        vector<int> sCount(26);
        vector<int> tCount(26);
        for(int i = 0; i < sLen; ++i) {
            sCount[s[i] - 'a']++;
        }
        for(int i = 0; i < tLen; ++i) {
            tCount[t[i] - 'a']++;
        }
        if(sCount != tCount) return false;
        return true;
    }
};

349. 兩個陣列的交集

題目連結:https://leetcode.cn/problems/intersection-of-two-arrays/
題目難度:簡單
文章講解:https://programmercarl.com/0349.兩個陣列的交集.html
影片講解: https://www.bilibili.com/video/BV1ba411S7wu
題目狀態:糾錯後透過

個人思路:

  1. 建立兩個unordered_map<int, int>型別的表分別存放兩個陣列中出現的數字和個數;
  2. 建立一個vector<int>型別的陣列res用來存放交集;
  3. 遍歷第一個map,若在第二個map中找到其鍵等於第一個map中的鍵,將其新增到res中;
  4. 遍歷完成後返回res

實現程式碼:

class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        vector<int> res;
        unordered_map<int, int> One;
        unordered_map<int, int> Two;
        for(auto &num : nums1) {
            One[num]++;
        }
        for(auto &num : nums2) {
            Two[num]++;
        }
        for(auto &num: One) {
            if(Two.find(num.first) != Two.end()) {
                res.push_back(num.first);
            }
        }
        return res;
    }
};

看了程式碼隨想錄中的思路,可以用unordered_set來實現,思路大致類似,但是寫的比我好多了,突然發現我程式碼中的map用的比較多餘,而且不需要將兩個陣列都存入map中,程式碼如下:

class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        unordered_set<int> result_set; // 存放結果,之所以用set是為了給結果集去重
        unordered_set<int> nums_set(nums1.begin(), nums1.end());
        for (int num : nums2) {
            // 發現nums2的元素 在nums_set裡又出現過
            if (nums_set.find(num) != nums_set.end()) {
                result_set.insert(num);
            }
        }
        return vector<int>(result_set.begin(), result_set.end());
    }
};

202. 快樂數

題目連結:https://leetcode.cn/problems/happy-number/
題目難度:簡單
文章講解:https://programmercarl.com/0202.快樂數.html
題目狀態:沒有思路😭

思路:

透過while(1)迴圈,反覆計算每個位置上數的平方和,直到平方和為1時結束,其中有一些細節:
定義一個unordered_set用來存放每次計算出的平方和的結果,若在遍歷中出現了之前存過的數,則表示會陷入無限迴圈,應該立即返回false

實現程式碼:

class Solution {
public:
    int getSum(int n) {
        int sum = 0;
        while(n) {
            sum += (n % 10) * (n % 10);
            n /= 10;
        }
        return sum;
    }
    bool isHappy(int n) {
        unordered_set<int> set;
        while(1) {
            int sum = getSum(n);
            if(sum == 1) {
                return true;
            }
            if(set.find(sum) != set.end()) {
                return false;
            } else {
                set.insert(sum);
            }
            n = sum;
        }
    }
};

1. 兩數之和

題目連結:https://leetcode.cn/problems/two-sum/
題目難度:簡單
文章講解:https://programmercarl.com/0001.兩數之和.html
影片講解:https://www.bilibili.com/video/BV1aT41177mK
題目狀態:有人相愛,有人夜裡開車看海,有人 leetcode 第一題都做不出來……

思路:

遍歷陣列nums,並將其存入到一個unordered_map型別中,其中鍵為陣列數值,值為該數值的下標,在遍歷的同時要執行下列操作:

  1. 判斷target - nums[i]的值是否存在在unordered_map中。若存在,則表示這兩個數值之和就等於target,返回這兩個數值的下標即可;
  2. 若不存在,則將nums[i]的值和下標存入到unordered_map中。

實現程式碼:

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        unordered_map<int, int> num;
        for(int i = 0; i < nums.size(); ++i) {
            auto iter = num.find(target - nums[i]);
            if(iter != num.end()) {
                return {iter->second, i};
            }
            num[nums[i]] = i;
        }
        return {};
    }
};

相關文章