面试经典150题 -- 哈希表(总结)

总的链接

面试经典 150 题 - 学习计划 - 力扣(LeetCode)全球极客挚爱的技术成长平台

面试经典150题 -- 哈希表(总结)_第1张图片

383 . 赎金信

用哈希表模拟 ;

用两个长为26的整数数组模拟哈希表,分别统计r和m中的频次,如果在m中字符出现的都比r中的小,那么m一定能够由r构成,否则,返回false;

class Solution {
public:
    bool canConstruct(string r, string m) {
        int a[26] , b[26] ;
        for(int i=0;i<26;i++){
            a[i] = 0 ;
            b[i] = 0 ;
        }
        for(char c : r){
            a[(int)(c-'a')]++;
        }
        for(char c : m){
            b[(int)(c-'a')]++;
        }
        for(int i=0;i<26;i++){
            if(a[i] > b[i]) return false;
        }
        return true ;
    }
};

205 同构字符串

哈希表模拟,一遍遍历,如果发生与之前映射产生冲突,直接返回false;

class Solution {
public:
    bool isIsomorphic(string s, string t) {
        unordered_map st;
        unordered_map ts;
        int n = s.size();
        for(int i=0;i

290 单词规律

与上题一样的思路 ;

class Solution {
public:
    bool wordPattern(string pattern, string s) {
        unordered_map stc;
        unordered_map cts;
        int m = s.size();
        int i = 0;
        for(auto ch : pattern){
            if(i>=m) return false;
            int j = i;
            while(j=m;
    }
};

242 . 有效的字母异位词

用两个数组来分别统计s和t中每种字母的出现频次,最后遍历判断即可 ;

class Solution {
public:
    bool isAnagram(string s, string t) {
        int sn[26] = { 0 } ;
        int tn[26] = { 0 } ;
        for(char c : s) sn[c-'a']++;
        for(char c : t) tn[c-'a']++;
        for(int i=0;i<26;i++){
            if(sn[i]!=tn[i]) return false;
        }
        return true;
    }
};

49 . 字母异位词分组

用一个unordered_map> mp,key存排序后的字符串,value存原来的字符串,一遍遍历,将排序之后相同的字符串全部加入到map[s]中,然后用vector>来返回结果 ;

class Solution {
public:
    vector> groupAnagrams(vector& strs) {
        vector> ans;
        unordered_map> smap;
        for(string s : strs){
            string tmp = s;
            sort(tmp.begin(),tmp.end());
            smap[tmp].emplace_back(s);
        }
        for(auto it = smap.begin();it!=smap.end();it++){
            ans.emplace_back(it->second);
        }
        return ans;
    }
};

1 . 两数之和

用一个哈希表(map)来存元素的值和对应的下标,题目要求nums[i]+nums[j]=target , 然后遍历的过程中对于nums[j],如果在之前的哈希表中能够找到target-nums[j],那么直接返回即可;

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

202 . 快乐数

哈希表模拟,如果遇到之前已经遇到过的,那么就会死循环 ;

class Solution {
public:
    int getsum(int n)
    {
        int sum = 0;
        while(n)
        {
            sum += pow(n%10,2);
            n /= 10;
        }
        return sum;
    }
    bool isHappy(int n) {
          unordered_set s;
          while(1)
          {
              int sum = getsum(n);
              if(sum==1) return true;
              if(s.find(sum)!=s.end()) return false;
              else s.insert(sum);
              n = sum;
          }
    }
};

219 . 存在重复元素

哈希表加滑动窗口

class Solution {
public:
    bool containsNearbyDuplicate(vector& nums, int k) {
        int n = nums.size();
        unordered_set s;
        for(int i=0;ik) s.erase(nums[i-k-1]);
            if(s.count(nums[i])) return true;
            s.emplace(nums[i]);
        }
        return false;
    }
};

128 . 最长连续序列

法一(双指针)

先排序 + 去重,然后用双指针模拟

class Solution {
public:
    int longestConsecutive(vector& nums) {
        if(nums.size()==0) return 0 ;
        sort(nums.begin(),nums.end()) ;
        nums.erase(unique(nums.begin(),nums.end()),nums.end()) ;
        int ans = 1  , n = nums.size();
        for(int i=0;i

 法二(哈希表):

O(n),先用哈希表将所有元素存下来,然后一遍遍历,在遍历的过程中,对每个序列开头,进行判断;

详细实现请看代码 : 

class Solution {
public:
    int longestConsecutive(vector& nums) {
        unordered_set num_set;
        for (const int& num : nums) {
            num_set.insert(num);
        }

        int longestStreak = 0;

        for (const int& num : num_set) {
            if (!num_set.count(num - 1)) {
                int currentNum = num;
                int currentStreak = 1;

                while (num_set.count(currentNum + 1)) {
                    currentNum += 1;
                    currentStreak += 1;
                }

                longestStreak = max(longestStreak, currentStreak);
            }
        }

        return longestStreak;           
    }
};

法三(dp)

先排序+去重 ;

然后dp找最大长度 ;

class Solution {
public:
    int longestConsecutive(vector& nums) {
        int n = nums.size();
        if(n==0) return 0;
        sort(nums.begin(),nums.end());
                // 使用 std::unique 函数移除重复元素,并返回指向新的逻辑结尾的迭代器
        auto it = std::unique(nums.begin(), nums.end());
        
        // 使用容器的 erase 函数擦除重复元素之后的部分
        nums.erase(it, nums.end());
        vector dp(n,1);
        int ans = 0;
        for(int i=1;i

你可能感兴趣的:(leetcode,算法学习,面试,算法,leetcode,哈希表)