【优选算法】Simulation-Phoenix:模拟算法的重生涅槃

文章目录

本篇是优选算法之模拟算法,是一种依据问题给定的规则与逻辑,按步骤细致地重现事件的发展流程,进而获取最终结果的算法

1.概念解析

🚩什么是模拟算法?

简单来说就是照葫芦画瓢,题目说啥就照着写代码就行,所以很考察代码能力

2.替换所有的问号

✏️题目描述:

✏️示例:

传送门: 替换所有的问号

题解:

这题很简单,显然是先遍历一遍数组,然后在遍历的时候,如果遇到就替换为与该位置前后都不相同的数,所以也要对要替换的数遍历一遍,直到发现合适的数

💻细节问题:

注意边界情况,没有两个相邻的数

💻代码实现:

cpp 复制代码
#include <iostream>
#include <vector>
using namespace std;

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 || ch != s[i - 1]) && (i == s.size() - 1 || ch != s[i + 1]))
                    {
                        s[i] = ch;
                        break;
                    }
                }
            }
        }
        return s;
    }
};

3.提莫攻击

✏️题目描述:

✏️示例:

传送门: 提莫攻击

题解:

做模拟算法题的精髓就是要画图,只有图画明白了,才能找到规律,而不是凭空想象

所以根据规律发现相邻两数之差是突破点,如果相邻两数之差大于duration,那么不用重置中毒时间;如果相邻两数之差小于duration,那么重置中毒时间

💻代码实现:

cpp 复制代码
#include <iostream>
#include <vector>
using namespace std;

class Solution 
{
public:
    int findPoisonedDuration(vector<int>& timeSeries, int duration) 
    {
        int ret = 0;
        for (int i = 1; i < timeSeries.size(); ++i)
        {
            int x = timeSeries[i] - timeSeries[i - 1];
            if (x >= duration)
            {
                ret += duration;
            }
            else
            {
                ret += x;
            }
        }
        return ret + duration;
    }
};

4.Z字形变换

✏️题目描述:

✏️示例:

传送门: Z字形变换

题解:

本题的意思是要你根据题目给出的Z字形字符串,将其从上到下从左至右的方式以一个新字符串的方式返回,显然这是一个找规律性极强的题目,所以画图!画图!画图!

💻第一步:

首先我们将每个数的索引按照Z字形填入,我们是从第一行开始录入,所以可以发现第一行最后一行都是一个等差数列,然后发现规律,公差是0~6之间元素的个数,所以得出d=2n-2

💻第二步:

接下来处理中间的行数,发现如图的1 ~ 7 ~ 135 ~ 11 ~ 17也是以6为公差,只不过是两个数两个数的差,所以得出规律(k,d-k)

💻细节问题:

注意for循环的判断条件为i < n || j < k,而不是&&,因为当一个越界之后,另一个可能还没越界判断完

💻代码实现:

cpp 复制代码
#include <iostream>
#include <vector>
using namespace std;

class Solution 
{
public:
    string convert(string s, int numRows)
    {
        if (numRows == 1)
        {
            return s;
        }
        string ret;
        int n = s.size();
        int d = 2 * numRows - 2;
        for (int i = 0; i < n; i += d)
        {
            ret += s[i];
        }
        for (int k = 1; k < numRows - 1; ++k)
        {
            for (int i = k, j = d - k; i < n || j < k; i += d, j += d)
            {
                if (i < n)
                {
                    ret += s[i];
                }
                if (j < n)
                {
                    ret += s[j];
                }
            }
        }
        for (int i = numRows - 1; i < n; i += d)
        {
            ret += s[i];
        }
        return ret;
    }
};

5.外观序列

✏️题目描述:

✏️示例:

传送门: 外观序列

题解:

其实题目意思就是对上一行的序列进行解释,比如第三行为21,那么第四行的意思就是一个2一个1

💻细节问题:

所以很明显这题要用双指针解决,因为要持续向后查找有几个相同的,直到不同为止

leftright都从0开始,然后right向后移动,直到该位置和前一个位置不相同,然后记录长度和数字,直接让left=right,开始下一段

💻代码实现:

cpp 复制代码
#include <iostream>
#include <string>
using namespace std;

class Solution
{
public:
    string countAndSay(int n)
    {
        string ret = "1";
        for (int i = 1; i < n;++i)
        {
            string tmp;
            int len = ret.size();
            for (int left = 0, right = 0; right < len; )
            {
                while (ret[left] == ret[right])
                {
                    right++;
                }
                tmp += to_string(right - left) + ret[left];
                left = right;
            }
            ret = tmp;
        }
        return ret;
    }
};

6.数青蛙

✏️题目描述:

✏️示例:

传送门: 数青蛙

题解:

要理解本题题意,就是一只青蛙要完整叫完croak,如果一只青蛙没叫完,那么就需要另一只青蛙来发出叫声

💻第一步:

首先,以如图所示为例子,第一个c,计入该位置为1,接下来到r该位置变为1上一个位置变为0,可以理解为一个1一直在移动,表示这个叫声遍历到哪里了,直到遍历到k为止

💻第二步:

注意在遍历过程中注意要像图中分类,对于字符c,若k位置不为0,那么表示有青蛙闲置,那么之前叫完的青蛙就可以再次叫对于其他字符,要找该字符的前一个字符符不符合croak的顺序和字符若不符合字符直接返回-1

💻细节问题:

注意处理完所有字符时,要判断一下是否还有没叫完的叫声

💻代码实现:

cpp 复制代码
#include <iostream>
#include <vector>
#include <unordered_map>
#include <string>
using namespace std;

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

        for (auto ch : croakOfFrogs)
        {
            if (ch == 'c')
            {
                if (hash[n - 1] != 0)
                {
                    hash[n - 1]--;
                }
                hash[0]++;
            }
            else
            {
                int i = index[ch];
                if (hash[i - 1] == 0)
                {
                    return -1;
                }
                hash[i - 1]--;
                hash[i]++;
            }
        }
        for (int i = 0; i < n - 1; ++i)
        {
            if (hash[i] != 0)
            {
                return -1;
            }
        }
        return hash[n - 1];
    }
};

希望读者们多多三连支持

小编会继续更新

你们的鼓励就是我前进的动力!

相关推荐
NullPointerExpection几秒前
java 中 main 方法使用 KafkaConsumer 拉取 kafka 消息如何禁止输出 debug 日志
java·kafka·log4j·slf4j
一只鹿鹿鹿11 分钟前
软件项目体系建设文档,项目开发实施运维,审计,安全体系建设,验收交付,售前资料(word原件)
java·大数据·运维·产品经理·设计规范
weixin_7499499024 分钟前
双向列表的实现(C++)
开发语言·c++·链表
NineData27 分钟前
NineData云原生智能数据管理平台新功能发布|2024年12月版
数据库·sql·算法·云原生·oracle·devops·ninedata
涔溪31 分钟前
idea无法使用nodejs
java·ide·intellij-idea
鱼忆梦31 分钟前
Idea日志乱码
java·ide·intellij-idea
bachelores37 分钟前
数据结构-栈、队列和数组
数据结构·算法
xianwu54340 分钟前
反向代理模块开发,
linux·开发语言·网络·c++·git
xsh8014424243 分钟前
Java Spring Boot监听事件和处理事件
java·前端·数据库
AQin10121 小时前
【Leetcode·中等·数组】59. 螺旋矩阵 II(spiral matrix ii)
算法·leetcode·矩阵·数组