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

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

模拟算法实战涵盖替换问号、提莫攻击、Z 字形变换、外观数列及数青蛙五道题目。核心策略为遍历模拟与状态追踪。替换问号需避开相邻重复字符;提莫攻击关注时间间隔与持续时间关系;Z 字形变换利用周期规律重构;外观数列迭代统计连续字符;数青蛙通过哈希表管理叫声状态。重点在于边界条件处理与逻辑严密性。

花里胡哨发布于 2026/3/21更新于 2026/6/1125 浏览
模拟算法实战:替换问号、提莫攻击、Z 字形变换等 5 题解析

模拟算法精选:五道经典题目深度解析

039 替换所有的问号

题目描述: 给定一个字符串 s,将其中的所有问号 ? 替换为小写英文字母。要求替换后不能出现连续重复的字符。

解题思路

采用纯模拟策略。遍历字符串,遇到问号时,尝试用 a~z 中的字符进行填充。关键在于检查该位置的前后字符,确保新填入的字符不与相邻字符重复。由于只有三个字符(前、后、自身)需要避让,而字母表有 26 个,必然存在至少一个合法字符。

代码实现

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++) {
                    // 检查前后是否冲突
                    if ((i == 0 || ch != s[i - 1]) && 
                        (i == s.size() - 1 || ch != s[i + 1])) {
                        s[i] = ch;
                        break;
                    }
                }
            }
        }
        return s;
    }
};

提示: 实际编码时注意边界条件,特别是首尾字符的判断,避免数组越界。


040 提莫攻击

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

解题思路

核心在于处理重叠区间。比较相邻两次攻击的时间差:

  1. 若时间差大于等于 duration,说明上次中毒已完全结束,累加完整时长。
  2. 若时间差小于 duration,说明中毒被刷新,只累加时间差部分。 最后别忘了加上最后一次攻击的完整持续时间。

代码实现

class Solution {
public:
    int findPoisonedDuration(vector<int>& timeSeries, int duration) {
        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;
            }
        }
        // 最后一次攻击必定贡献完整的 duration
        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"。

解题思路

本质是迭代统计连续相同字符的个数。使用双指针 left 和 right 扫描当前字符串,当字符不同时,记录个数并拼接字符,作为下一轮输入。

代码实现

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 的青蛙可用则复用,否则新增一只。
  • 遇到其他字符:检查前驱状态是否存在,不存在则非法。
  • 最终检查所有青蛙是否都完成了叫声(即没有卡在中间状态的青蛙)。

代码实现

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. 模拟算法精选:五道经典题目深度解析
  2. 039 替换所有的问号
  3. 解题思路
  4. 代码实现
  5. 040 提莫攻击
  6. 解题思路
  7. 代码实现
  8. 041 Z 字形变换
  9. 解题思路
  10. 代码实现
  11. 042 外观数列
  12. 解题思路
  13. 代码实现
  14. 043 数青蛙
  15. 解题思路
  16. 代码实现
  • 💰 8折买阿里云服务器限时8折了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • C++ 实现:基于正倒排索引的 Boost 搜索引擎
  • C++ 面试高频考点:从语言特性到虚函数机制
  • 哈希表原理与 C++ 实战实现
  • C++ 继承机制详解
  • C++ unordered 系列容器使用与模拟实现
  • Linux C++ 多进程编程:fork 函数与进程管理机制
  • Java 并发编程核心:CompletableFuture 实战与原理解析
  • PyCharm 与 GitHub Copilot 配置指南:学生认证与安全设置
  • 量子仿真新进展:Walsh-Hadamard 变换硬件架构优化解析
  • UG NX 逆向工程设计流程:STL 导入与网格优化
  • 大型语言模型(LLMs)架构与现状解析
  • LLM 大模型学习精要:基础概念与优化实践
  • 10 款主流 AI 写作辅助工具功能测评与对比
  • To B 产品经理如何转型 AI 产品经理:路径与价值分析
  • C++ 类和对象(中):默认成员函数与运算符重载
  • Stable Diffusion 秋叶整合包部署与实战指南
  • 基于 OpenClaw 快速搭建企业微信 AI 客服
  • OpenClaw 部署方案对比:云端、WSL、Mac 与虚拟机实战
  • Python 批量解析 EML 邮件文件存成 txt 利用 AI 辅助生成年终总结
  • Windows 下 MinIO 服务搭建与 Web 控制台访问指南

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如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