20210501:字符串与哈希表力扣专题学习记录

字符串与哈希表力扣专题学习记录

题目

    1. 字母异位词分组
      在这里插入图片描述
    1. 无重复字符的最长子串
      在这里插入图片描述
    1. 重复的DNA序列
      在这里插入图片描述
    1. 最小覆盖子串
      在这里插入图片描述

思路与算法

    1. 字母异位词分组 : 按照字母序排序后再映射即可
    1. 无重复字符的最长子串:标准滑窗+HashSet或者HashMap实现。
    1. 重复的DNA序列:同上,滑窗加HashMap实现。
    1. 最小覆盖子串:滑窗加HashMap实现,区别在于使用几个map来完成映射。

代码实现

    1. 字母异位词分组
class Solution {
public:
    vector<vector<string>> groupAnagrams(vector<string>& strs) {
        
        map<string,vector<string>> anagram;
        vector<vector<string>> res;

        for (int i = 0; i < strs.size(); ++i) {
            // 拿到当前字符串,并按照字母序进行排序
            string str = strs[i];
            sort(str.begin(),str.end());

            // 如果无法在anagram中找到
            if (anagram.find(str) == anagram.end()) {
                vector<string> item;
                anagram.insert(make_pair(str,item));
            }
            anagram[str].push_back(strs[i]);
        }
        map<string,vector<string>>::iterator it;
        for (it = anagram.begin(); it != anagram.end(); ++it) {
            res.push_back((*it).second);
        }
        return res;
    }
};
    1. 无重复字符的最长子串
class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        if(s.size() == 0) 
            return 0;
        unordered_set<char> lookup;
        int maxStr = 0;
        int left = 0;
        for(int i = 0; i < s.size(); i++){
            // 若之前出现过,此时需要移动左指针,直至出现一个全新的字符
            while (lookup.find(s[i]) != lookup.end()){
                lookup.erase(s[left]);
                left ++;
            }
            // 正常情况下直接更新当前最大值即可
            maxStr = max(maxStr,i-left+1);
            lookup.insert(s[i]);
    }
        return maxStr;
        
    }
};
    1. 重复的DNA序列
class Solution {
    public List<String> findRepeatedDnaSequences(String s) {
        HashSet<String> seen = new HashSet<>();
        HashSet<String> output = new HashSet<>();
        int len = s.length();
        int L = 10;
        for (int i = 0; i < len - L + 1; ++i) {
            String tmp_string = s.substring(i,i + L);
            if (seen.contains(tmp_string)) {
                output.add(tmp_string);
            }
            seen.add(tmp_string);
        }
        return new LinkedList<String> (output);
    }
}
    1. 最小覆盖子串
class Solution {
public:
    unordered_map<char,int> ori,cnt;

    bool check(){
        for (const auto &p : ori) {
            if (cnt[p.first] < p.second) {
                return false;
            }
        }
        return true;
    }

    string minWindow(string s, string t) {
        // 将要检索包含的字符扔进ori图计数
        for (const auto &c : t) {
            ori[c]++;
        }

        int l = 0, r = -1;
        int len = INT_MAX, ansL = -1;

        // 遍历
        while ( r < int(s.size()) ) {
            // 将s中与t中都出现过的字符计数存在cnt图中,存的是s中的字符和计数
            if ( ori.find(s[++r]) != ori.end() ) {
                cnt[s[r]]++;
            }
            // 满足s中出现的字符个数和种类都大于等于t中要求的,才能继续进行
            while (check() && l <= r) {
                // 满足要求,则更新满足要求的最小的len,同时更新ansL
                if (r - l + 1 < len) {
                    len = r - l + 1;
                    ansL = l;
                }
                // 此时左指针右移,判断是否还满足条件
                if (ori.find(s[l]) != ori.end()) {
                    cnt[s[l]]--;
                }
                l++;
            }
        }

        return ansL == -1 ? string() : s.substr(ansL,len);
    }
};

写在最后

  1. 滑动窗口加Hash是非常常用的一种数据结构模式,和DFS以及BFS一样,非常的常用,务必熟练书写掌握。注意一些细节写法,例如隐含初始值,一般为-1。例如Java和Cpp中的map的使用的区别,哪个方便哪个来,不要拘泥死板,灵活使用。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IMMUNIZE

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值