哈希表与字符串

预备知识

1.哈希表:给定表M,存在函数f(key),对任意的关键字值key,代入函数后若能得到包含该关键字的表中地址,称表M为哈希(Hash)表,函数f(key)为哈希(Hash) 函数。

在这里插入图片描述

2.字符哈希

统计字符个数,字符为下标【key】,个数为值【value】
在这里插入图片描述

3.哈希表排序整数

数组做哈希,下标为整数,自动排序
在这里插入图片描述

4.任意元素的映射

利用哈希函数,转换为整数,再对表长取余
在这里插入图片描述

5.发生冲突

在这里插入图片描述

6.拉链法解决冲突,构造哈希表【指针数组】【头插法】

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

7.哈希map与STL map

在这里插入图片描述

一,最长回文串

LeetCode 409. Longest Palindrome

1.用数组实现哈希:即下标为key,对应的值为value

2.是否有中心点,及其计算,比较讨巧

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

class Solution {
public:
    int longestPalindrome(string s) {
        int char_map[128]={0};
        int max_length=0;
        int flag=0;//是否有中心点
        for(int i=0;i<s.length();i++){
            char_map[s[i]]++;//利用整数的数组下标实现字符哈希,统计字符个数
        }
        for(int i=0;i<128;i++){
            if(char_map[i]%2==0){
                max_length+=char_map[i];
            }
            else{
                max_length+=char_map[i]-1;//如果是奇数,可以有中心点,且舍去一个
                flag=1;
            }
        }
        return max_length+flag;
    }
};

作者:xia-mu-lao-zhang-ren
链接:https://leetcode-cn.com/problems/longest-palindrome/solution/zui-chang-hui-wen-zi-chuan-by-xia-mu-lao-vknq/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

二,词语模式

LeetCode 290. Word Pattern

1.根据空格划分单词

2.建立【字符串和字符】的映射

3.建立映射与否,字符是否使用过,是否不够或多余

4.没有映射就添加一个,有就继续往后添加,通过if实现此功能

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

class Solution {
public:
    bool wordPattern(string pattern, string s) {
        map<string,char>word_map;//单词-字符
        char used[128]={0};
        string word;//临时保存拆分的单词
        int pos=0;//当前指向pattern的字符
        s.push_back(' ');//s尾部追加一个空格,使得遇到空格拆分单词,无需特殊处理了
        for(int i=0;i<s.length();i++){
            if(s[i]==' '){//遇到空格,即拆分一个新单词
                if(pos==pattern.length()){//pos走到头了,length=3,[0,1,2]
                    return false;
                }
                //若单词没有出现在哈希映射中
                if(word_map.find(word)==word_map.end()){
                    if(used[pattern[pos]]){//如果当前字符已使用
                        return false;
                    }
                    word_map[word]=pattern[pos];//如果未使用,新加映射
                    used[pattern[pos]]=1;
                }
                //若单词出现在哈希映射中
                else{
                    if(word_map[word]!=pattern[pos]){
                        return false;
                    }
                }
                //完成一个单词的插入和查询后,清空word,指针迁移
                word="";
                pos++;

            }
            else{
                word+=s[i];//划分单词
            }
        }
        if(pos!=pattern.length()){
            return false;//有多余的pattern字符
        }
        return true;



    }
};

作者:xia-mu-lao-zhang-ren
链接:https://leetcode-cn.com/problems/word-pattern/solution/dan-ci-gui-lu-by-xia-mu-lao-zhang-ren-qt1f/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

三,同字符词语分组

LeetCode 49. Group Anagrams

1.颠倒字母顺序就是【字符数相同】

2.怎样建立映射,排好序的字符,字符数量

3.有的就加入,没有的就新加映射

在这里插入图片描述
在这里插入图片描述

方法一,以内部进行排序的各个单词为 key

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

class Solution {
public:
//一个字符,映射一个字符数组
    //各个字符数量相同的字符串
    //若str未未出出现现在anagram中,设置str到一个空字符串向量的映射。
    vector<vector<string>> groupAnagrams(vector<string>& strs) {
        map<string,vector<string> >anagram;
        vector<vector<string> >result;
        for(int i=0;i<strs.size();i++){//遍历各个单词
            string str=strs[i];//临时保存该单词
            sort(str.begin(),str.end());
            if(anagram.find(str)==anagram.end()){//若str未未出出现现在anagram中,设置str到一个空字符串向量的映射。
                vector<string> item;
                anagram[str]=item;
            }
            anagram[str].push_back(strs[i]); //在对应的字符串向量中push结果【 anagram[str]指的是vector<string>】         
        }
        map<string,vector<string> >::iterator it;
        for(it=anagram.begin();it!=anagram.end();it++){
            result.push_back((*it).second);
        }
        return result;
    }
};

作者:xia-mu-lao-zhang-ren
链接:https://leetcode-cn.com/problems/group-anagrams/solution/zi-mu-yi-wei-ci-fen-zu-by-xia-mu-lao-zha-l1l5/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

方法二:以26个字母的字符数量为key
在这里插入图片描述
在这里插入图片描述

void change_to_vector(string &str,vector<int>&vec){
    for(int i=0;i<26;i++){
        vec.push_back(0);
    }
    for(int i=0;i<str.length();i++){
        vec[str[i]-'a']++;//将str中的字符串各个字符个数进行统计并存入vec中
    }
}
class Solution {
public:
    vector<vector<string>> groupAnagrams(vector<string>& strs) {
        map<vector<int> ,vector<string> >anagram;
        vector<vector<string> >result;
        for(int i=0;i<strs.size();i++){
            vector<int>vec;
            change_to_vector(strs[i],vec);
            if(anagram.find(vec)==anagram.end()){
                vector<string>item;
                anagram[vec]=item;
            }
            anagram[vec].push_back(strs[i]);
        }
        map<vector<int>,vector<string> >::iterator it;
        for(it=anagram.begin();it!=anagram.end();it++){
            result.push_back((*it).second);
        }
        return result;
    }
};

四,无重复字符的最长子串

LeetCode 3. Longest Substring Without Repeating Characters
滑动窗口

1.用字符哈希记录并【检验】是否有新加入的重复元素

2.滑动窗口

3.维护窗口,调整头指针【前进到重复元素的后一位】,更新结果【清空】【补充】

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        int begin=0;//头指针
        int result=0;
        string word="";//加个空格就错了
        int char_map[128]={0};//数组哈希
        for(int i=0;i<s.length();i++){
            char_map[s[i]]++;//用哈希数组记录各个字符的个数
            if(char_map[s[i]]==1){
                word+=s[i];
                if(result<word.length()){
                    result=word.length();//更新最大长度
                }
            }
            else{
                while(begin<i&&char_map[s[i]]>1){//调整begin的位置,清除char_map中重复的字符
                    char_map[s[begin]]--;
                    begin++;
                }
                word="";
                for(int j=begin;j<=i;j++){//从新的begin开始重新更新word,改变的不是begin,然后再进行i的for循环
                    word+=s[j];
                }
            }
        }
        return result;

    }
};

作者:xia-mu-lao-zhang-ren
链接:https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/solution/wu-zhong-fu-zi-fu-de-zui-chang-zi-chuan-33z96/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

五,重复的DNA序列

LeetCode 187. Repeated DNA Sequences

方法一:哈希map,枚举字符串中所有长度为10的子串,记录所有子串数量

有就加进去,没有就新加映射

在这里插入图片描述
在这里插入图片描述

class Solution {
public:
    vector<string> findRepeatedDnaSequences(string s) {
        map<string,int>word_map;//<单词,单词数量>映射
        vector<string>result;
        for(int i=0;i<s.length();i++){
            string word=s.substr(i,10);
            if(word_map.find(word)!=word_map.end()){//若在哈希表中出现
                word_map[word]+=1;
            }
            else{
                word_map[word]=1;//没有出现就添加进去
            }
        }
        map<string,int>::iterator it;
        for(it=word_map.begin();it!=word_map.end();it++){
            if(it->second>1){
                result.push_back(it->first);
            }
        }
        return result;
    }
};

作者:xia-mu-lao-zhang-ren
链接:https://leetcode-cn.com/problems/repeated-dna-sequences/solution/zhong-fu-de-dnaxu-lie-by-xia-mu-lao-zhan-vu4v/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

方法二:整数编码,【左移右移运算未掌握】【未解决】

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

六,最小窗口子串

LeetCode 76. Minimum Window Substring

1.滑动窗口 ,就是【看字符数量】,和顺序无关

2.字符哈希统计s,t字符数量

3.将t中出现的字符push到vec中

4.数组下标也可以是char

5.如何维护最小窗口,头指针移动的2个条件

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


class Solution {
private:
    bool is_window_ok(int map_s[],int map_t[],vector<int>&vec_t){
    for(int i=0;i<vec_t.size();i++){
        if(map_s[vec_t[i]]<map_t[vec_t[i]]){
            return false;//如果s出现的字符数量小于t中该字符的数量
        }
    }
            return true;
}
public:
    string minWindow(string s, string t) {
        const int max_array_len=128;//char 0-127,用数组下标记录字符个数
        int map_t[max_array_len]={0};
        int map_s[max_array_len]={0};
        vector<int>vec_t;//记录t字符串中有哪些字符
        for(int i=0;i<t.length();i++){
            map_t[t[i]]++;//遍历t,记录各个字符的个数
        }
        for(int i=0;i<max_array_len;i++){
            if(map_t[i]>0){
                vec_t.push_back(i);//遍历,将字符串t中出现的字符存储到vec_c中【为啥是i?】
            }
        }
        int window_begin=0;
        string result;
        for(int i=0;i<s.length();i++){
            map_s[s[i]]++;//遍历s,记录各个字符的个数
            while(window_begin<i){//窗口头指针小于尾指针
            char begin_ch=s[window_begin];//窗口头指针指向的字符
            if(map_t[begin_ch]==0){//【数组里应该是整型,结果是char】//如果没有出现过
                window_begin++;
                }
            else if(map_s[begin_ch]>map_t[begin_ch]){//出现了,数量足够,两个a
                map_s[begin_ch]--;
                window_begin++;
            }
            else{
                break;
            }           
            }
            if(is_window_ok(map_s,map_t,vec_t)){
                int new_window_len=i-window_begin+1;
                if(result==""||result.length()>new_window_len){
                    result=s.substr(window_begin,new_window_len);//如果有更短的就更新result
                }
            }
        }
        return result;
        

    }
};
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值