算法6--模拟

基础

模拟类型的算法题就是根据题目的要求,使用代码模拟实现某个过程,有时可能会需要找规律来对代码进行一定的优化。

经典例题

1576. 替换所有的问号

给你一个仅包含小写英文字母和 ‘?’ 字符的字符串 s,请你将所有的 ‘?’ 转换为若干小写字母,使最终的字符串不包含任何 连续重复 的字符。
注意:你 不能 修改非 ‘?’ 字符。
题目测试用例保证 除 ‘?’ 字符 之外,不存在连续重复的字符。
在完成所有转换(可能无需转换)后返回最终的字符串。如果有多个解决方案,请返回其中任何一个。可以证明,在给定的约束条件下,答案总是存在的。

class Solution {
public:
    string modifyString(string s) {
        int i=0;
        for(;i<s.size();++i){
            if('?'!=s[i]){
                continue;
            }
            char c='a';
            if(i>0){
                c=s[i-1]+1;
                c='a'+(c-'a')%26;
            }
            while(i+1<s.size()&&c==s[i+1]){
                c++;
                c='a'+(c-'a')%26;
            }
            s[i]=c;
        }

        return s;
    }
};

495. 提莫攻击

在《英雄联盟》的世界中,有一个叫 “提莫” 的英雄。他的攻击可以让敌方英雄艾希(编者注:寒冰射手)进入中毒状态。
当提莫攻击艾希,艾希的中毒状态正好持续 duration 秒。
正式地讲,提莫在 t 发起攻击意味着艾希在时间区间 [t, t + duration - 1](含 t 和 t + duration - 1)处于中毒状态。如果提莫在中毒影响结束 前 再次攻击,中毒状态计时器将会 重置 ,在新的攻击之后,中毒影响将会在 duration 秒后结束。
给你一个 非递减 的整数数组 timeSeries ,其中 timeSeries[i] 表示提莫在 timeSeries[i] 秒时对艾希发起攻击,以及一个表示中毒持续时间的整数 duration 。
返回艾希处于中毒状态的 总 秒数。

int findPoisonedDuration(int* timeSeries, int timeSeriesSize, int duration)
{
    int wholetime=0;
    int i=0;
    for(i=0;i+1<timeSeriesSize;++i)
    {
        if(timeSeries[i]+duration<=timeSeries[i+1])
        {
            wholetime+=duration;
        }
        else
        {
            wholetime+=timeSeries[i+1]-timeSeries[i];
        }
    }
    wholetime+=duration;
    
    return wholetime;
}

6. Z 字形变换

将一个给定字符串 s 根据给定的行数 numRows ,以从上往下、从左到右进行 Z 字形排列。
比如输入字符串为 “PAYPALISHIRING” 行数为 3 时,排列如下:
P A H N
A P L S I I G
Y I R
之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:“PAHNAPLSIIGYIR”。
请你实现这个将字符串进行指定行数变换的函数

找规律这道题就可以很好地解决

class Solution {
public:
    string convert(string s, int numRows) {
        if(1==numRows){
            return s;
        }
        int i=0;
        string ans;
        for(i=0;i<numRows;++i){
            int j=i;
            int k=1;
            int span1=2*(numRows-i-1);
            int span2=2*i;
            span1=(0==span1?span2:span1);
            span2=(0==span2?span1:span2);
            while(j<s.size()){
                ans+=s[j];
                1==k%2?j+=span1:j+=span2;
                k++;
            }
        }
        
        return ans;
    }
};

38. 外观数列

「外观数列」是一个数位字符串序列,由递归公式定义:
countAndSay(1) = “1”
countAndSay(n) 是 countAndSay(n-1) 的行程长度编码。
行程长度编码(RLE)是一种字符串压缩方法,其工作原理是通过将连续相同字符(重复两次或更多次)替换为字符重复次数(运行长度)和字符的串联。例如,要压缩字符串 “3322251” ,我们将 “33” 用 “23” 替换,将 “222” 用 “32” 替换,将 “5” 用 “15” 替换并将 “1” 用 “11” 替换。因此压缩后字符串变为 “23321511”。
给定一个整数 n ,返回 外观数列 的第 n 个元素。

class Solution {
public:
    string countAndSay(int n) {
        if(1==n){
            return "1";
        }
        string ret=countAndSay(n-1);
        string ans;
        int i=1;
        int count=1;
        for(;i<=ret.size();++i){
            if(i==ret.size()||ret[i-1]!=ret[i]){
                ans+=to_string(count);
                ans.push_back(ret[i-1]);
                count=1;
                continue;
            }
            ++count;
        }

        return ans;
    }
};

1419. 数青蛙

给你一个字符串 croakOfFrogs,它表示不同青蛙发出的蛙鸣声(字符串 “croak” )的组合。由于同一时间可以有多只青蛙呱呱作响,所以 croakOfFrogs 中会混合多个 “croak” 。
请你返回模拟字符串中所有蛙鸣所需不同青蛙的最少数目。
要想发出蛙鸣 “croak”,青蛙必须 依序 输出 ‘c’, ’r’, ’o’, ’a’, ’k’ 这 5 个字母。如果没有输出全部五个字母,那么它就不会发出声音。如果字符串 croakOfFrogs 不是由若干有效的 “croak” 字符混合而成,请返回 -1 。

使用一个哈希表分别记录正在发出声音c、r、o、a、k的青蛙的个数,遍历字符串 croakOfFrogs,如果是字符r、o、a、k之一,如果它的前一个字符的数量为0,说明该字符串不是有效字符,直接返回-1即可,否则前一个字符的数量减1,当前字符的数量加1;如果当前当前字符是c,先对当前字符的数量加1,接着检查字符k的数量是否为0,非0就减1,否则什么也不做。遍历结束后,如果c、r、o、a对应的数量为0,说明字符串是有效字符,k对应的数量就是模拟字符串中所有蛙鸣所需不同青蛙的最少数目,否则说明字符串无效返回-1。

class Solution {
public:
    int minNumberOfFrogs(string croakOfFrogs) {
        map<char,int> mp;
        mp['c']=0;
        mp['r']=1;
        mp['o']=2;
        mp['a']=3;
        mp['k']=4;
        vector<int> count(5,0);
        int i=0;
        for(i=0;i<croakOfFrogs.size();++i){
            if('c'==croakOfFrogs[i]){
                count[0]+=1;
                if(count[4]){
                    count[4]--;
                }
            }
            else {
                if(!count[mp[croakOfFrogs[i]]-1]){
                    return -1;
                }
                count[mp[croakOfFrogs[i]]-1]--;
                count[mp[croakOfFrogs[i]]]++;
            }
        }
        for(i=0;i<4;++i){
            if(count[i]){
                return -1;
            }
        }

        return count[4];
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值