算法:模拟
1.替换所有的问号
1576. 替换所有的问号 - 力扣(LeetCode)
- 遍历字符串:通过外层循环逐一检查每个字符。
- 遇到
?
时处理:- 内层循环遍历小写字母(
'a'
到'z'
)。 - 对每个字母检查是否满足:
- 与前一个字符不同(若
?
在开头则无需检查)。 - 与后一个字符不同(若
?
在末尾则无需检查)。
- 与前一个字符不同(若
- 找到符合条件的字母后,立即将
?
替换为该字母。
- 内层循环遍历小写字母(
- 返回结果:修改后的字符串
class Solution
{
public:string modifyString(string s) {for(int i = 0; i < s.size(); i++){if(s[i] == '?'){for(char ch = 'a'; ch <= 'z'; ch++){if((i == 0 || s[i - 1] != ch) &&(i == s.size() - 1 || s[i + 1] != ch)){s[i] = ch;}}}}return s;}
};
2.提莫攻击
495. 提莫攻击 - 力扣(LeetCode)
思路:计算后一个值减前一个值与中毒时间比较,大于等于这个中毒时间就直接加上这个中毒时间,否则就加上这个间隔时间。
class Solution
{
public:int findPoisonedDuration(vector<int>& timeSeries, int duration){int ret = 0;ret += duration;for(int i = 1; i <= timeSeries.size() - 1; i++){if(timeSeries[i] - timeSeries[i - 1] >= duration){ret += duration;}else{ret += timeSeries[i] - timeSeries[i - 1];}}return ret;}
};
3. Z字形变换
6. Z 字形变换 - 力扣(LeetCode)
思路:找规律 公差d = 2 * numRows - 2 (n为字符串s的长度)。每一行每一行的处理元素(下标索引)
numRows == 1时直接返回字符串s
第一行:0 -> 0 + d -> 0 + 2d ->......-> 0 + kd。
第x行(1 <= x < numRows - 1)两个数两个数向后走:(x, d - x)-> (x + d, d - x + d) -> ......->(x + kd, d - x + kd)。
最后一行:numRows - 1 -> numRows - 1 + d -> ...... -> numRows - 1 + kd。
- 第一行:索引为0, d, 2d, 3d, ... 直到超出字符串长度。
- 中间行(从第2行到第numRows-1行):每一行有两个序列。第一个序列起始为当前行号x(从0开始则行号为x,注意第一行是x=0),步长为d;第二个序列起始为d-x,步长也为d。注意这两个序列在同一周期内,且每一行中这两个索引交替出现(但按顺序是先第一个序列的,再第二个序列的,然后进入下一周期)。
- 最后一行(第numRows行,索引为numRows-1):索引为(numRows-1), (numRows-1)+d, (numRows-1)+2d, ...
class Solution
{
public:string convert(string s, int numRows) {if(numRows == 1)return s;int d = 2 * numRows - 2, n = s.size();string ret;//处理第一行for(int i = 0; i < n; i += d){ret += s[i];}//处理中间行for(int k = 1; k < numRows - 1; k++){for(int i = k, j = d - k; i < n || j < n; i += d, j += d){if(i < n)ret += s[i];if(j < n)ret += s[j];}}//最后一行for(int i = numRows - 1; i < n; i += d){ret += s[i];}return ret;}
};
4.外观数列
38. 外观数列 - 力扣(LeetCode)
思路:模拟+双指针
- 使用双指针法识别连续相同字符:
left
:标记当前字符组的起始位置right
:向前扫描直到遇到不同字符
- 计算连续字符长度:
len = right - left
- 生成描述字符串:
"长度" + "字符"
- 每轮处理完成后,将结果赋值给
ret
作为下一轮输入
class Solution
{
public:string countAndSay(int n){string ret = "1";for(int i = 1; i < n; i++)//解释n - 1次ret{string tmp;for(int left = 0, right = 0; right < ret.size();){while(right < ret.size() && ret[left] == ret[right])right++;int len = right - left;tmp += to_string(len) + ret[left];left = right;}ret = tmp;}return ret;}
};
5.数青蛙
1419. 数青蛙 - 力扣(LeetCode)
思路:模拟,要保证找到青蛙的最小个数,遍历字符串,并且将字符放入哈希表中(放入规则如下)
当遍历到字符r , o , a , k时,找前驱字符是否存在哈希表中,存在则前驱个数--,当前字符++;不存在则返回 -1。
当遍历到字符c时,找到最后一个字符是否在哈希表中存在,存在则最后一个字符--,当前字符++;不存在当前字符++。
直接用if-else的写法
class Solution
{
public:int minNumberOfFrogs(string croakOfFrogs) {unordered_map<char, int> hash = {{'c',0}, {'r',0}, {'o',0}, {'a',0}, {'k',0}};for(int i = 0; i < croakOfFrogs.size(); i++){if(croakOfFrogs[i] == 'c'){if(hash['k'] > 0){hash['k']--;}hash['c']++;}else if(croakOfFrogs[i] == 'r'){if(hash['c'] > 0){hash['c']--;hash['r']++;}else{return -1;}}else if(croakOfFrogs[i] == 'o'){if(hash['r'] > 0){hash['r']--;hash['o']++;}else{return -1;}}else if(croakOfFrogs[i] == 'a'){if(hash['o'] > 0){hash['o']--;hash['a']++;}else{return -1;}}else if(croakOfFrogs[i] == 'k'){if(hash['a'] > 0){hash['a']--;hash['k']++;}else{return -1;}}}if(hash['c'] > 0 || hash['r'] > 0 || hash['o'] > 0 || hash['a'] > 0)return -1;elsereturn hash['k'];}
};
这个写法不太好,可以在用一个哈希表来存储这个字符及其对应的下标。
class Solution
{
public:int minNumberOfFrogs(string croakOfFrogs) {string ret = "croak";int n = ret.size();vector<int> hash(n);//用数组来模拟哈希表unordered_map<char,int> index;//当前字符的下标for(int i = 0; i < n; i++)//映射下标{index[ret[i]] = i;}for(auto e : croakOfFrogs){if(e == 'c'){if(hash[n - 1] != 0)hash[n - 1]--;hash[0]++; }else{int i = index[e];if(hash[i - 1] != 0){hash[i - 1]--;hash[i]++;}elsereturn -1;}}for(int i = 0; i < n - 1; i++){if(hash[i] != 0)return -1;}return hash[n - 1];}
};