力扣387—字符串中的第一个唯一字符
相关标签:队列、哈希表、字符串、计数
题意
给定一个字符串 s
,找到 它的第一个不重复的字符,并返回它的索引 。如果不存在,则返回 -1
。
解法1—暴力循环
class Solution
{
public:
int firstUniqChar(string s)
{
//解法1:暴力循环
int len=s.size();
bool flag=true;
for(int i=0;i<len;++i)
{
flag=true;
for(int j=0;j<len;++j)
{
if(i==j)
continue;
if(s[i]==s[j])
{
flag=false;
break;
}
}
if(flag)
return i;
}
return -1;
}
};
解法2—哈希表
由于题目说了字母都是小写,我们可以建立一个长度为26的数组,作为哈希表。
此解法时间复杂度为 O(n),空间复杂度为O(1)。
class Solution
{
public:
int firstUniqChar(string s)
{
//解法1:暴力循环
/*
int len=s.size();
bool flag=true;
for(int i=0;i<len;++i)
{
flag=true;
for(int j=0;j<len;++j)
{
if(i==j)
continue;
if(s[i]==s[j])
{
flag=false;
break;
}
}
if(flag)
return i;
}
return -1;
*/
// 哈希表,字母都是小写
vector<int> vec(26);
for(int i=0;i<s.size();++i)
{
vec[s[i]-'a']++;
}
for(int i=0;i<s.size();++i)
{
if(vec[s[i]-'a']==1)
return i;
}
return -1;
}
};
解法3—队列
class Solution
{
public:
int firstUniqChar(string s)
{
//解法1:暴力循环
/*
int len=s.size();
bool flag=true;
for(int i=0;i<len;++i)
{
flag=true;
for(int j=0;j<len;++j)
{
if(i==j)
continue;
if(s[i]==s[j])
{
flag=false;
break;
}
}
if(flag)
return i;
}
return -1;
*/
// 哈希表,字母都是小写
/*
vector<int> vec(26);
for(int i=0;i<s.size();++i)
{
vec[s[i]-'a']++;
}
for(int i=0;i<s.size();++i)
{
if(vec[s[i]-'a']==1)
return i;
}
return -1;
*/
//队列
unordered_map<char,int> position; // (元素,元素下标)
queue<pair<char,int>> q; //(元素,元素下标)
int len=s.size();
for(int i=0;i<len;++i)
{
if(position.count(s[i])==0)
{
//在哈希表中没出现过
//首个唯一字符会被放在队列头部(因为最先插入队列)
position[s[i]]=i;
q.emplace(s[i],i);
}
else
{
//字符已经在哈希表中出现过了
position[s[i]]=-1;//既然出现过了,就讲哈希表中的对应元素的值改为 -1
while(!q.empty()&&position[q.front().first]==-1)
{
//如果队列不为空,并且队列头部元素已经出现次数≥2了(即position[队头元素]==-1)
//我们就移除队头元素。
//可能有些出现次数超过2次的元素依然在队列中,但没关系,这些元素肯定不在队列头部
//因为我们最后返回的是队头元素
//这就叫「延迟删除」技巧。
q.pop();
}
}
}
return q.empty()?-1:q.front().second;
}
};
力扣383—赎金信
相关标签:哈希表、字符串、计数
题意
给你两个字符串:ransomNote 和 magazine ,判断 ransomNote 能不能由 magazine 里面的字符构成。如果可以,返回 true ;否则返回 false 。magazine 中的每个字符只能在 ransomNote 中使用一次。
解法1—自己写的不知道什么解法
class Solution
{
public:
bool canConstruct(string ransomNote, string magazine)
{
for(int i=0;i<ransomNote.size();++i)
{
if(magazine.size()==0)
return false;
int index = magazine.find(ransomNote[i]);
if(index==string::npos)
return false;
else
{
magazine.erase(index,1);
}
}
return true;
}
};
效率太低了,呜呜
解法2—哈希表
题目说了,只包含小写字母,我们可以创建一个长度为为26的vector充当哈希表,先遍历magazine中的字符,将字符出现次数进行一个统计。再遍历ransomNote中的每一个字符,然后字符出现的次数减一,如果出现次数小于0了,就证明ransomNote中的该字符比magazine中的该字符多,于是返回false,最后遍历结束返回true。
class Solution
{
public:
bool canConstruct(string ransomNote, string magazine)
{
/*
菜鸡解法
for(int i=0;i<ransomNote.size();++i)
{
if(magazine.size()==0)
return false;
int index = magazine.find(ransomNote[i]);
if(index==string::npos)
return false;
else
{
magazine.erase(index,1);
}
}
return true;
*/
//哈希表解法
vector<int> vec(26);
for(char ch:magazine)
vec[ch-'a']++;
for(char ch:ransomNote)
{
vec[ch-'a']--;
if(vec[ch-'a']<0)
return false;
}
return true;
}
};
力扣242—有效的字母异位词
相关标签:哈希表、字符串、排序
题意
给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。
注意:若 s 和 t 中每个字符出现的次数都相同,则称 s 和 t 互为字母异位词。
解题思路—哈希表
不多说了,哈希表走起!
class Solution
{
public:
bool isAnagram(string s, string t)
{
if(s.size()!=t.size())
return false;
vector<int>vec(26);
for(int i=0;i<s.size();++i)
{
vec[s[i]-'a']++;
vec[t[i]-'a']--;
}
for(int i=0;i<26;++i)
if(vec[i]!=0)
return false;
return true;
}
};