跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI 生图工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C++算法

模拟算法实战:替换问号、提莫攻击、Z 字形变换等 5 题详解

模拟算法专题涵盖替换问号、提莫攻击、Z 字形变换、外观数列及数青蛙五道经典题目。核心在于通过遍历字符串或数组,结合边界条件判断与状态追踪解决问题。例如提莫攻击需计算时间间隔与中毒时长的最小值,Z 字形变换利用周期规律重组字符,数青蛙则通过统计各阶段字符数量确定最少并发青蛙数。代码实现以 C++ 为主,注重逻辑清晰与边界处理。

技术博主发布于 2026/3/27更新于 2026/9/1168 浏览
模拟算法实战:替换问号、提莫攻击、Z 字形变换等 5 题详解

模拟算法专题:5 道经典题目解析

本专题聚焦于模拟类算法,涵盖字符串处理、时间序列计算及状态追踪。以下通过 C++ 实现五道典型题目,重点在于理清逻辑边界与优化遍历策略。

039 替换所有的问号

题目描述: 给定一个字符串 s,将其中所有的问号 ? 替换为小写英文字母,使得最终结果中不包含连续重复的字符。

解题思路

采用纯模拟策略。从左到右遍历字符串,遇到 ? 时,尝试用 a~z 填充。关键在于检查左右邻居是否相同,确保当前字符不与前后冲突。

代码实现

class Solution {
public:
    string modifyString(string s) {
        for (int i = 0; i < s.size(); i++) {
            if (s[i] == '?') {
                // 尝试 a-z 填充
                for (char ch = 'a'; ch <= 'z'; ch++) {
                    // 检查左邻居和右邻居
                    bool left_ok = (i == 0 || ch != s[i - 1]);
                    bool right_ok = (i == s.size() - 1 || ch != s[i + 1]);
                    if (left_ok && right_ok) {
                        s[i] = ch;
                        break;
                    }
                }
            }
        }
        return s;
    }
};

040 提莫攻击

题目描述: 在《英雄联盟》中,提莫的攻击会让目标中毒持续 duration 秒。给定攻击时间序列 timeSeries,计算总中毒时长。

解题思路

核心是计算相邻两次攻击的时间间隔。如果间隔大于等于 duration,则上次中毒完整持续;否则,只计算间隔时间。最后一次攻击必定贡献完整的 duration。

代码实现

class Solution {
public:
    int findPoisonedDuration(vector<int>& timeSeries, int duration) {
        if (timeSeries.empty()) return 0;
        int ret = 0;
        int n = timeSeries.size();
        
        for (int i = 1; i < n; i++) {
            int x = timeSeries[i] - timeSeries[i - 1];
            if (x >= duration) {
                ret += duration;
            } else {
                ret += x;
            }
        }
        // 加上最后一次攻击的完整持续时间
        return ret + duration;
    }
};

041 Z 字形变换

题目描述: 将字符串按照给定的行数 numRows 以 Z 字形排列,然后按行读取生成新字符串。

解题思路

观察规律可知,字符排列具有周期性,周期 T = 2 * numRows - 2。

  • 第一行和最后一行是公差为 T 的等差数列。
  • 中间行除了首尾元素外,每两个一组围绕周期的倍数对称分布。

代码实现

class Solution {
public:
    string convert(string s, int numRows) {
        if (numRows == 1) return s;
        
        string ret;
        int d = 2 * numRows - 2;
        int n = s.size();
        
        // 1. 处理第一行
        for (int i = 0; i < n; i += d) ret += s[i];
        
        // 2. 处理中间行
        for (int k = 1; k < numRows - 1; k++) {
            for (int i = k, j = d - k; i < n || j < n; i += d, j += d) {
                if (i < n) ret += s[i];
                if (j < n) ret += s[j];
            }
        }
        
        // 3. 处理最后一行
        for (int i = numRows - 1; i < n; i += d) ret += s[i];
        
        return ret;
    }
};

042 外观数列

题目描述: 返回外观数列的第 n 项。该数列由前一项的数字读法生成(如 "1" -> "11" -> "21")。

解题思路

本质是模拟'读'的过程。遍历上一项字符串,统计连续相同字符的个数,拼接成新的字符串。

代码实现

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 (right < len && ret[left] == ret[right]) right++;
                tmp += to_string(right - left) + ret[left];
                left = right;
            }
            ret = tmp;
        }
        return ret;
    }
};

043 数青蛙

题目描述: 给定字符串 croakOfFrogs,由多个青蛙发出的 "croak" 组成。求最少需要多少只青蛙才能发出这个叫声序列。

解题思路

模拟青蛙的状态流转。维护一个数组记录当前处于 c, r, o, a, k 各阶段的青蛙数量。

  • 遇到 c:若没有刚结束叫唤的青蛙(即 k 阶段),则新增一只;否则复用。
  • 遇到其他字符:必须存在前驱状态的青蛙,将其状态后移。
  • 最后所有青蛙必须都完成叫唤(回到 k 或空闲),否则非法。

代码实现

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

以上题目均侧重于对业务逻辑的抽象与模拟,掌握此类思维有助于解决大量涉及状态机或流程控制的工程问题。

目录

  1. 模拟算法专题:5 道经典题目解析
  2. 039 替换所有的问号
  3. 解题思路
  4. 代码实现
  5. 040 提莫攻击
  6. 解题思路
  7. 代码实现
  8. 041 Z 字形变换
  9. 解题思路
  10. 代码实现
  11. 042 外观数列
  12. 解题思路
  13. 代码实现
  14. 043 数青蛙
  15. 解题思路
  16. 代码实现

更多推荐文章

查看全部
  • 数据结构:双向链表详解与实现
  • 视觉 Transformer (ViT) 原理与代码实现
  • 计算机专业就业真相:数据怎么说,个人怎么选
  • Topaz Photo AI 核心功能解析:AI 降噪、锐化与无损放大技术
  • ComfyUI Photoshop 插件配置指南:实现 AI 绘画工作流
  • 风险管控而非修补:金仓 SQL 防火墙体系化实践
  • 华为OD机试真题:日志解析算法题解
  • Stable Diffusion 部署实战:Stability Matrix 与 LiblibAI 使用指南
  • AI一键生成爆款短视频!2026最强提示词模板+实战案例
  • 后端视角下的 HTML 前端基础入门
  • Python+UniApp 博物馆文创产品推荐商城系统
  • AI 绘画在商业设计中的应用与版权解析
  • BeyondCompare 安装与本地试用状态管理
  • AI 产品经理学习路线:从零基础到专家的进阶指南
  • Sora 2 / Veo 3.1来了!2026 AI视频生成技术最新突破解读
  • 跳表核心原理与 C++ 实现深度解析
  • AI 模型调优与 Python 实战
  • C++ Connector 与 MySQL:配置陷阱与性能优化深度解析
  • MVP 至千万级并发:AI 在前后端开发中的差异化落地指南
  • Veristand 环境安装教程:Linux RT 与 Windows 平台

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online