目录
模拟算法
模拟模拟:也就是题目给你怎么算,已经告诉你了,所以你按照题目的来就行了
特定:比较简单
模拟算法流程(一定要在草稿纸上过一遍流程)
考察的就是你把题目转换成代码的能力
例题
leetcode1576例题

按照题目要求,从前往后遍历,只要有?,那就替换,从a还是试到z即可
class Solution {
public:
string modifyString(string s) {
int n=s.size();
for(int i=0;i<n;i++){
if(s[i]=='?'){
for(char ch='a';ch<='z';ch++){
if((i==0||ch!=s[i-1])&&(i+1==n||ch!=s[i+1]))
{
s[i]=ch;
break;
}
}
}
}
return s;
}
};
leetcode495例题


也就是跟着题意走,按照过程模拟一遍转换成代码即可
class Solution {
public:
int findPoisonedDuration(vector<int>& timeSeries, int duration) {
int ret=0;
for(int i=0;i<timeSeries.size();i++){
if(i+1<=timeSeries.size()-1&&timeSeries[i+1]-timeSeries[i]>=duration){
ret+=duration;
}
else if(i+1<=timeSeries.size()-1&&timeSeries[i+1]-timeSeries[i]<duration){
ret+=timeSeries[i+1]-timeSeries[i];
}
else{
ret+=duration;
}
}
return ret;
}
};
leetcode6例题

题目理解:就是给一串字符串,然后按照从上往下,从左往右排成z字形
算法原理讲解:
一、按照题目模拟,开辟一个额外的数组,直接按照题目的要求存进去即可,然后再取出来拍成一排
二、找规律

可以发现如果是第一行和最后一行,下标就是+公差,
比如n=4的时候,0+6=6,6+6=12,公差可能看出来2n-2(最后一行同理)
只有中间行因为是斜的,还需要额外找规律
但是发现1+6=7,5+6=11
所以中间行就是两个两个一起走,第一个数就是k行开头,即k,第二个数即d-k
所以就是(k,d-k)两个数字一起动
注意:
1.如果n=1的话就有问题,n=1是一直排下去,但是公差就会计算出错,导致死循环,n=要特殊处理
2.注意,如果某个下标计算超出边界,就去下一行计算
class Solution {
public:
string convert(string s, int numRows) {
// 处理n=1的情况
if (numRows == 1) {
return s;
}
// n>1
int n = s.size();
string ret;
for (int i = 0; i < numRows; i++) {
int d = 2 * numRows - 2;
if (i == 0 || i == numRows - 1) {
for (int j = 0;; j++) {
if (i + j*d < n)
ret.push_back(s[i+j*d]);
else
break;
}
}
else{
for (int j = 0;; j++) {
if (i + j*d < n)
ret.push_back(s[i+j*d]);
else break;
if(d-i+j*d<n)
ret.push_back(s[d-i+j*d]);
else break;
}
}
}
return ret;
}
};
leetcode38例题

算法原理讲解:
按照题目模拟即可
使用双指针来找相同的数,比如right往右边找,一直找到right!=left的时候,然后此时记录一下个数,个数就是right-left,然后left=right即可,一直循环到right找到头即可
class Solution {
public:
string countAndSay(int n) {
string ret="1";
for(int i=1;i<n;i++){
string tmp;
for(int left=0,right=0;right<ret.size();){
while(right<ret.size()&&ret[left]==ret[right]) right++;
tmp+=to_string(right-left)+ret[left];
left=right;
}
ret=tmp;
}
return ret;
}
};
leetcode1419例题

题目原理讲解:
青蛙蛙叫:croak
一个字符串代表了青蛙的蛙叫
比如示例1,croakcroak,一只青蛙就行,叫完第一声croak,再叫一声croak,所以一只就够了
示例2,crcoakroak,一只cr oak,没有叫完的时候不能再叫,所以只能有第二只croak来叫,所以返回两只
示例3:由于不是croak,所以返回-1

借助hash表,假设从前往后遍历,第一个碰到c,所以hash里面c是1,然后遍到r,r的前面有c,所以r变为1,c变为0,(注意:这里表示第一只青蛙从c叫到r了),然后遍历到c,此时hash里面就是c:1 r:1
然后遍历o,hash中c:1 r:0 o:1 (这个o为1是前面的r变来的)
所以每次遍历到某个字母的时候,我们要看hash中对应的字母的前面一个是否有,有才说明是连贯的,没有就返回-1即可,当遍历到k=1的时候,说明完整的一只出来了,只要k=1就说明一只青蛙完成了叫,所以后面要是碰到c,就需要k--,c++,这样就可以使青蛙重复叫了
如果遍历完字符,在hash中除了k有数量之外其他应该为0,如果不为0的话说明有问题返回-1即可

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;
}
int pos=0;
while(pos<croakOfFrogs.size()){
if(croakOfFrogs[pos]==ret[0]){
if(hash[n-1]>0) hash[n-1]--;
hash[0]++;
}
else{
//此时是中间的字符
int tmp=index[croakOfFrogs[pos]];//tmp为当前下标,tmp-1就是前驱下标
if(hash[tmp-1]){
hash[tmp-1]--;
hash[tmp]++;
}
else return -1;
}
pos++;
}
for(int i=0;i<hash.size()-1;i++){
if(hash[i]!=0)
return -1;
}
return hash[n-1];
}
};
总结:
模拟算法就是按照题目要求来,题目要干啥就干啥,一般题目都会告诉你怎么做,如果时间复杂度和空间复杂度过大,就需要寻找规律,在规律当中优化
171万+

被折叠的 条评论
为什么被折叠?



