前言
👧个人主页:@小沈YO.
😚小编介绍:欢迎来到我的乱七八糟小星球🌝
📋专栏:优选算法
🔑本章内容:模拟
记得 评论📝 +点赞👍 +收藏😽 +关注💞哦~
一、模拟示例:
1.1 替换所有的问号
- 题⽬链接:1576. 替换所有的问号
- 题⽬描述:
- 解法(模拟):
算法思路:
纯模拟。从前往后遍历整个字符串,找到问号之后,就⽤ a ~ z 的每⼀个字符去尝试替换即可 - C++代码
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;
break;
}
}
}
}
return s;
}
};
1.2 提莫攻击
- 题⽬链接:495. 提莫攻击
- 题⽬描述:
- 解法(模拟 + 分情况讨论):
算法思路:
模拟 + 分情况讨论。
计算相邻两个时间点的差值:
i. 如果差值⼤于等于中毒时间,说明上次中毒可以持续 duration 秒;
ii. 如果差值⼩于中毒时间,那么上次的中毒只能持续两者的差值。 - C++代码
class Solution {
public:
int findPoisonedDuration(vector<int>& timeSeries, int duration)
{
int cnt=0;
for(int i=1;i<timeSeries.size();i++)
{
cnt+=(timeSeries[i]-timeSeries[i-1])>duration?duration:timeSeries[i]-timeSeries[i-1];
}
cnt+=duration;
return cnt;
}
};
1.3 N 字形变换
- 题⽬链接:6. N 字形变换
- 题⽬描述:
- 解法(模拟 + 找规律):
算法思路:
找规律,⽤ row 代替⾏数,row = 4 时画出的 N 字形如下:
0 2row - 2 4row - 4
1 2row - 3 2row - 1 4row - 5 4row - 3
2 2row-4 2row 4row - 6 4row - 2
3 2row + 1 4row - 1
不难发现,数据是以 2row - 2 为⼀个周期进⾏规律变换的。将所有数替换成⽤周期来表⽰的变量:
第⼀⾏的数是:0, 2row - 2, 4row - 4;
第⼆⾏的数是:1, (2row - 2) - 1, (2row - 2) + 1, (4row - 4) - 1, (4row - 4) + 1;
第三⾏的数是:2, (2row - 2) - 2, (2row - 2) + 2, (4row - 4) - 2, (4row - 4) + 2;
第四⾏的数是:3, (2row - 2) + 3, (4row - 4) + 3。
可以观察到,第⼀⾏、第四⾏为差为 2row - 2 的等差数列;第⼆⾏、第三⾏除了第⼀个数取值为⾏数,每组下标为(2n - 1, 2n)的数围绕(2row - 2)的倍数左右取值。 以此规律,我们可以写出迭代算法。 - C++代码
class Solution {
public:
string convert(string s, int numRows)
{
string ret;
if(numRows==1)return s;
int d=2*numRows-2;//公差
//处理第一行
for(int i=0;i<s.size();i+=d)
{
ret+=s[i];
}
//处理中间行
for(int k=1;k<numRows-1;k++)
{
for(int i=k,j=d-i;i<s.size()||j<s.size();i+=d,j+=d)
{
if(i<s.size())ret+=s[i];
if(j<s.size())ret+=s[j];
}
}
//处理最后一行
for(int i=numRows-1;i<s.size();i+=d)
{
ret+=s[i];
}
return ret;
}
};
1.4 外观数列
- 题⽬链接:38. 外观数列
- 题⽬描述:
- 解法(模拟):
算法思路:所谓「外观数列」,其实只是依次统计字符串中连续且相同的字符的个数。依照题意,依次模拟即可 - C++代码
class Solution {
public:
string countAndSay(int n) {
string s = "1";
if (n == 1)
return "1";
string str;
for(int i=2;i<=n;i++)
{
int cnt = 1;
str.clear();
for (int i = 0; i < s.size() - 1; i++)
{
if (s[i] == s[i + 1])
cnt++;
else
{
if (cnt >= 1)
str += to_string(cnt);
str += s[i];
cnt = 1;
}
}
if (cnt >= 1)
str += to_string(cnt);
str += s[s.size() - 1];
s=str;
}
return str;
}
};
1.5 数⻘蛙
- 题⽬链接:1419. 数⻘蛙
- 题⽬描述:
- 解法(模拟 + 分情况讨论)
算法思路:模拟⻘蛙的叫声。
- 当遇到 ‘r’ ‘o’ ‘a’ ‘k’ 这四个字符的时候,我们要去看看每⼀个字符对应的前驱字符,有没有⻘蛙叫出来。如果有⻘蛙叫出来,那就让这个⻘蛙接下来喊出来这个字符;如果没有,直接返回 -1 ;
- 当遇到 ‘c’ 这个字符的时候,我们去看看 ‘k’ 这个字符有没有⻘蛙叫出来。如果有,就让这个⻘蛙继续去喊 ‘c’ 这个字符;如果没有的话,就重新搞⼀个⻘蛙。
- C++代码
//1.if~else形式
class Solution {
public:
int minNumberOfFrogs(string croakOfFrogs)
{
unordered_map<char,int> hash;
for(int i=0;i<croakOfFrogs.size();i++)
{
hash[croakOfFrogs[i]]++;
if(croakOfFrogs[i]=='c')
{
if(hash['k']==0)continue;
else hash['k']--;
}
else if(croakOfFrogs[i]=='r')
{
if(hash['c']==0)return -1;
else hash['c']--;
}
else if(croakOfFrogs[i]=='o')
{
if(hash['r']==0)return -1;
else hash['r']--;
}
else if(croakOfFrogs[i]=='a')
{
if(hash['o']==0)return -1;
else hash['o']--;
}
else
{
if(hash['a']==0)return -1;
else hash['a']--;
}
}
if(hash['c']==0&&hash['r']==0&&hash['o']==0&&hash['a']==0)
return hash['k'];
else return -1;
}
};
------------------------------------------------------------------------------------------------
//2 映射
class Solution {
public:
int minNumberOfFrogs(string croakOfFrogs)
{
string t="croak";
int n=t.size();
vector<int> hash(n);
unordered_map<char,int> index;
for(int i=0;i<n;i++)index[t[i]]=i;
char ch;
for(auto&ch:croakOfFrogs)
{
if(ch=='c')
{
if(hash[n-1]!=0)hash[n-1]--;
hash[0]++;
}
else
{
int j=index[ch];
if(hash[j-1]!=0)
{
hash[j-1]--;
hash[j]++;
}
else return -1;
}
}
for(int i=0;i<n-1;i++)
if(hash[i]!=0)return -1;
return hash[n-1];
}
};