文章目录
- 205. 同构字符串
- 1002. 查找共用字符
- 925. 长按键入
- 844.比较含退格的字符串
- 栈模拟
- 双指针
205. 同构字符串
class Solution {
public:
bool isIsomorphic(string s, string t) {
unordered_map<char, char> map1;
unordered_map<char, char> map2;
for(int i=0, j=0; i<s.size(); i++, j++)
{
// map1保存s[i] 到 t[j]的映射
if(map1.find(s[i]) == map1.end()) map1[s[i]] = t[j];
// map2保存t[j] 到 s[i]的映射
if(map2.find(t[j]) == map2.end()) map2[t[j]] = s[i];
//比较
if(map1[s[i]] != t[j] || map2[t[j]] != s[i]) return false;
}
return true;
}
};
1002. 查找共用字符
统计出搜索字符串里26个字符的出现的频率,然后取每个字符频率最小值,最后转成输出格式
void *memset(void *s, int ch, size_t n);
函数解释:将s中当前位置后面的n个字节(typedef unsigned int size_t)用 ch 替换并返回s。
memset的作用是在一段内存块中填充某个给定的值,它是对较大的结构体或数组进行清零操作的一种最快方法,也就是将已开辟内存空间 s 的首 n 个字节的值设为值(非数值型字符) c。
class Solution {
public:
vector<string> commonChars(vector<string>& words) {
vector<string> result;//保存输出结果
int hash[26] = {0};//统计所有字符的频率
//1.剔除
if(words.size() == 0) return result;
//2.用words的第一个字符初始化hash
for(int j=0; j<words[0].size(); j++)
{
hash[words[0][j] - 'a']++;
}
//for(int word : words[0]) hash[word - 'a']++;
//3.统计words其他字符串的频率 并更新hash
int hash1[26] = {0};//统计words中除第一个字符串的频率
for(int i=1; i<words.size(); i++)
{
//清零hash1 0填充hash1 大小是26*sizeof(int)
memset(hash1, 0, 26*sizeof(int));
for(int j = 0; j <words[i].size(); j++)
{
//统计words其他字符串的频率
hash1[words[i][j] - 'a']++;
}
//用hash1更新hash中的最小频率 遍历26个字母
for(int i=0; i<26; i++)
{
hash[i] = min(hash[i], hash1[i]);
}
}
//4.转化输出结果 遍历26个字母
for(int i=0; i<26; i++)
{
//题目中包括重复字符
while(hash[i] != 0)
{
string temp(1, i + 'a');//char转string
result.push_back(temp);
hash[i]--;//保存一次字符 频率减少一次
}
}
return result;
}
};
925. 长按键入
双指针,同时遍历name和type, 时间复杂度:
O
(
n
)
O(n)
O(n),空间复杂度:
O
(
1
)
O(1)
O(1),有三种情况
- name和type都遍历完了
- name[i]和type[j]相同,i和j继续移动
- name[i]和type[j]不相同
- 如果type[j]的第一个字符就不同,即j=0时就不相同,false
- 如果type[j]的第一个字符相同,j继续移动,跳过重复项。再次比较name[i]和type[j],如果相同,i和j继续移动;如果不相同,false
- name没有遍历完,false
- type没有遍历完,遍历剩余项,比较type[j]和type[j-1]
class Solution {
public:
bool isLongPressedName(string name, string typed) {
int i=0, j=0;
while(i<name.size() && j<typed.size())
{
if(name[i] == typed[j])
{
i++;
j++;
}
else
{
if(j == 0) return false;//如果第一位就不相同 返回false
// j跨越重复项,向后移动,同时防止j越界
while(j<typed.size() && typed[j] == typed[j-1]) j++;
//跨越重复项后继续比较
if(name[i] == typed[j])
{
i++;
j++;
}
else return false;
}
}
//name没有匹配完
if(i < name.size()) return false;
//type没有匹配完
while(j < typed.size())
{
if(typed[j] == typed[j-1]) j++;
else return false;
}
return true;
}
};
844.比较含退格的字符串
栈模拟
- 空间复杂度 O ( n + m ) O(n+m) O(n+m),时间复杂度 O ( n + m ) O(n+m) O(n+m)
- 如果不是#字符,累加字符;如果是#字符且栈非空,弹出栈顶字符。最后比较两个栈是否一样
写法1
class Solution {
public:
bool backspaceCompare(string s, string t) {
//方法1 栈模拟
string ss;//当成栈
string st;//当成栈
for(int i=0; i<s.size(); i++)
{
if(s[i] != '#') ss += s[i];
else if(!ss.empty()) ss.pop_back();
}
for(int i=0; i<t.size(); i++)
{
if(t[i] != '#') st += t[i];
else if(!st.empty()) st.pop_back();
}
if(ss == st) return true;
return false;
}
};
写法2
class Solution {
public:
bool backspaceCompare(string s, string t) {
//方法1 栈模拟 写法2
string ss = stackStr(s, '#');//当成栈
string st = stackStr(t, '#');//当成栈
if(ss == st) return true;
return false;
}
private:
string stackStr(string& s, char c)
{
string ss;
for(int i=0; i<s.size(); i++)
{
if(s[i] != c) ss += s[i];
else if(!ss.empty()) ss.pop_back();
}
return ss;
}
};
双指针
- 空间复杂度 O ( 1 ) O(1) O(1),时间复杂度 O ( n + m ) O(n+m) O(n+m)
- 双指针同时从后向前遍历S和T,记录#的数量,模拟消除的操作,就是#的数量减1。
- 如果#用完了,比较S[i]和T[j],如果S[i]和T[j]不相同返回false。如果S或者T其中一个遍历完了,也返回false。
- 最后如果S和T同时遍历完了,返回true,否则false。
class Solution {
public:
bool backspaceCompare(string s, string t) {
//方法2 双指针模拟
int sSkipNum = 0;//记录s中#数量
int tSikpNum = 0;//记录t中#数量
int i = s.size()-1;
int j = t.size()-1;
while(1)
{
//处理s中#字符
while(i >= 0)
{
//模拟s中#退回操作
if(s[i] == '#') sSkipNum++;//记录#数量
else
{
if(sSkipNum > 0) sSkipNum--;//相当于用了一次# 模拟退回操作
else break;//文本为空 跳出循环
}
i--;
}
while(j >= 0)
{
//模拟t中#退回操作
if(t[j] == '#') tSikpNum++;
else
{
if(tSikpNum > 0) tSikpNum--;
else break;
}
j--;
}
//s和t有一个遍历完了跳出循环
if(i < 0 || j < 0) break;
//比较s和t剩余字符
if(s[i] != t[j]) return false;
i--;
j--;
}
//说明S和T同时遍历完毕
if(i == -1 && j == -1) return true;
else return false;
}