数据结构与算法-字符串与哈希表
往期内容
1-链表
2-栈与队列
3-树与图
4-哈希表
5-查找
6-排序
7-贪心
8-递归与分治
9-动态规划
1.最长回文串
Leetcode-409 最长回文串
思路:利用一个数组,记录所有的字符的个数,如果该位置的个数是偶数个,全部记录下来,如果是奇数个,减1在全部记录下来,并定义一个flag保存中心奇数点。
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.size();i++)
{
char_map[s[i]]++;
}
for(int i=0;i<128;i++)
{
if(char_map[i]%2==0)
{
max_length+=char_map[i];
}
else
{
if(!flag)
{
flag=1;
}
max_length=max_length+(char_map[i]-1);
}
}
return max_length+flag;
}
};
2.单词规律
Leetcode-290 单词规律
思路:利用一个数组统计,模式串中的每个字符是否出现过,利用一个map记录字符串和对于模式的关系,当找到一个新的字符串的时候:查找它是否在map中,检查是否完全匹配,当它不在时,检查与之对应的value是否已经出现在数组中,如果在,表示之前有值与之匹配,返回false,否则将键值插入到map集合中。
class Solution {
public:
bool wordPattern(string pattern, string s) {
//map的映射 string->char
map<string,char> word_map;
char used[128]={0};
string word;
int pos=0;
s.push_back(' ');//尾部添加一个空格,方便处理
for(int i=0;i<s.size();i++)
{
if(s[i]==' ')//表示拆分到了一个单词
{
if(pos==pattern.size())//1.查到尾部,s长 pattern短
return false;
if(word_map.find(word)==word_map.end())//单词不在哈希映射中
{
if(used[pattern[pos]]==1){
return false;
}
word_map[word]=pattern[pos];
used[pattern[pos]]=1;
}
else
{
if(word_map[word]!=pattern[pos])
{
return false;
}
}
word="";
pos++;
}
else
{
word+=s[i];
}
}
if(pos!=pattern.size())//pattern长,s短
{
return false;
}
return true;
}
};
3.字母异位词分组
Leetcode-49 字母异位词分组
思路1:排序
class Solution {
public:
vector<vector<string>> groupAnagrams(vector<string>& strs) {
vector<vector<string>> result;
map<string,vector<string>> anagrams;
for(int i=0;i<strs.size();i++)
{
string s=strs[i];
sort(s.begin(),s.end());
if(anagrams.find(s)==anagrams.end())
{
vector<string> temp_s;
anagrams[s]=temp_s;
}
anagrams[s].push_back(strs[i]);
}
for(map<string,vector<string>>::iterator it=anagrams.begin();it!=anagrams.end();it++)
{
result.push_back((*it).second);
}
return result;
}
};
思路2:vector容器记录所有的位置和每个位置出现的次数
class Solution {
public:
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.size();i++)
{
vec[str[i]-'a']++;
}
}
vector<vector<string>> groupAnagrams(vector<string>& strs) {
map<vector<int>,vector<string>> anagrans;
vector<vector<string>> result;
for(int i=0;i<strs.size();i++)
{
vector<int> vec;
change_to_vector(strs[i],vec);
if(anagrans.find(vec)==anagrans.end())
{
vector<string> item;
anagrans[vec]=item;
}
anagrans[vec].push_back(strs[i]);
}
for(map<vector<int>,vector<string>>::iterator it=anagrans.begin();it!=anagrans.end();it++)
{
result.push_back((*it).second);
}
return result;
}
};
4.无重复字符的最长子串-重要
Leetcode-3 无重复字符的最长子串
思路:窗口思想,用begin和i维护一个窗口的大小
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.size();i++)
{
char_map[s[i]]++;
if(char_map[s[i]]==1)//没有出现过该字符
{
word+=s[i];
if(result<word.length())
result=word.length();
}
else//删除重复s[i]
{
while(begin<i && char_map[s[i]]>1){
char_map[s[begin]]--;
begin++;
}
word="";
for(int j=begin;j<=i;j++)
word+=s[j];
}
}
return result;
}
};
5.重复的DNA序列
Leetcode-187 重复的DNA序列
思路:map:建子串,值出现的次数,如果改子串在map中,值加1,否则将改子串插入到map中,最后遍历整个map得出结果
class Solution {
public:
vector<string> findRepeatedDnaSequences(string s) {
map<string,int> word_map;
vector<string> result;
if(s.size()<10) return {};
for(int i=0;i<s.size()-9;i++)
{
string word=s.substr(i,10);
if(word_map.find(word)!=word_map.end())
{
word_map[word]+=1;
}
else
{
word_map[word]=1;
}
}
for(map<string,int>::iterator it=word_map.begin();it!=word_map.end();it++)
{
if(it->second>1)
result.push_back(it->first);
}
return result;
}
};
6.最小覆盖子串
class Solution {
public:
//检测是否包含所有字符
bool is_baohan_char(int map_s[],int map_t[],vector<int> &vec)//检查窗口是否包含所有的字符
{ //map_s记录窗口s串中各个字符的个数
for(int i=0;i<vec.size();i++)
{
if(map_s[vec[i]]<map_t[vec[i]])
return false;
}
return true;
}
string minWindow(string s, string t) {
const int MAX_ARRAY_LEN=128;
int map_t[MAX_ARRAY_LEN]={0};
int map_s[MAX_ARRAY_LEN]={0};
vector<int> vect;
for(int i=0;i<t.size();i++)
{
map_t[t[i]]++;
}
for(int i=0;i<MAX_ARRAY_LEN;i++)
{
if(map_t[i]>0)
{
vect.push_back(i);
}
}
int window_begin=0;
string result;
for(int i=0;i<s.size();i++)
{
map_s[s[i]]++;
while(window_begin<i)//有重复元素
{
char begin_char=s[window_begin];
if(map_t[begin_char]==0)
{
window_begin++;
}
else if(map_s[begin_char]>map_t[begin_char])
{
map_s[begin_char]--;
window_begin++;
}
else
{
break;
}
}
if(is_baohan_char(map_s,map_t,vect))
{
int new_window_len=i-window_begin+1;
if(result=="" || result.size()>new_window_len)
{
result=s.substr(window_begin,new_window_len);
}
}
}
return result;
}
};
7.有效的字母异位词
Leetcode-242 有效的字母异位词
方法1:排序
方法2:哈希表,用数组记录字符的位置
class Solution {
public:
bool isAnagram(string s, string t) {
//方法2:字母表
if(s.size()!=t.size()) return false;
vector<int> s_vec(26,0);
vector<int> t_vec(26,0);
for(int i=0;i<s.size();i++)
{
s_vec[s[i]-'a']++;
t_vec[t[i]-'a']++;
}
for(int i=0;i<26;i++)
{
if(s_vec[i]!=t_vec[i])
return false;
}
return true;
}
};