轻松掌握模拟算法:从题目到代码

目录

模拟算法

例题

leetcode1576例题

leetcode495例题

leetcode6例题

leetcode38例题

leetcode1419例题

总结:


模拟算法

模拟模拟:也就是题目给你怎么算,已经告诉你了,所以你按照题目的来就行了

特定:比较简单

模拟算法流程(一定要在草稿纸上过一遍流程)

考察的就是你把题目转换成代码的能力

例题

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];
    }
};

总结:

模拟算法就是按照题目要求来,题目要干啥就干啥,一般题目都会告诉你怎么做,如果时间复杂度和空间复杂度过大,就需要寻找规律,在规律当中优化

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值