【优选算法之模拟】No.8--- 经典模拟算法


前言

在这里插入图片描述

👧个人主页:@小沈YO.
😚小编介绍:欢迎来到我的乱七八糟小星球🌝
📋专栏:优选算法
🔑本章内容:模拟
记得 评论📝 +点赞👍 +收藏😽 +关注💞哦~


一、模拟示例:

1.1 替换所有的问号

  1. 题⽬链接:1576. 替换所有的问号
  2. 题⽬描述:
    在这里插入图片描述
  3. 解法(模拟):
    算法思路:
    纯模拟。从前往后遍历整个字符串,找到问号之后,就⽤ a ~ z 的每⼀个字符去尝试替换即可
  4. 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 提莫攻击

  1. 题⽬链接:495. 提莫攻击
  2. 题⽬描述:
    在这里插入图片描述
  3. 解法(模拟 + 分情况讨论):
    算法思路:
    模拟 + 分情况讨论。
    计算相邻两个时间点的差值:
    i. 如果差值⼤于等于中毒时间,说明上次中毒可以持续 duration 秒;
    ii. 如果差值⼩于中毒时间,那么上次的中毒只能持续两者的差值。
  4. 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 字形变换

  1. 题⽬链接:6. N 字形变换
  2. 题⽬描述:
    在这里插入图片描述
  3. 解法(模拟 + 找规律):
    算法思路:
    找规律,⽤ 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)的倍数左右取值。 以此规律,我们可以写出迭代算法。
  4. 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 外观数列

  1. 题⽬链接:38. 外观数列
  2. 题⽬描述:
    在这里插入图片描述
  3. 解法(模拟):
    算法思路:所谓「外观数列」,其实只是依次统计字符串中连续且相同的字符的个数。依照题意,依次模拟即可
  4. 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 数⻘蛙

  1. 题⽬链接:1419. 数⻘蛙
  2. 题⽬描述:
    在这里插入图片描述
  3. 解法(模拟 + 分情况讨论)
    算法思路:模拟⻘蛙的叫声。
  • 当遇到 ‘r’ ‘o’ ‘a’ ‘k’ 这四个字符的时候,我们要去看看每⼀个字符对应的前驱字符,有没有⻘蛙叫出来。如果有⻘蛙叫出来,那就让这个⻘蛙接下来喊出来这个字符;如果没有,直接返回 -1 ;
  • 当遇到 ‘c’ 这个字符的时候,我们去看看 ‘k’ 这个字符有没有⻘蛙叫出来。如果有,就让这个⻘蛙继续去喊 ‘c’ 这个字符;如果没有的话,就重新搞⼀个⻘蛙。
  1. 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];
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小沈YO.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值