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

Java 模拟算法实战:LeetCode 经典题解

通过五个典型 LeetCode 案例,深入讲解 Java 中的模拟算法。涵盖字符替换边界处理、时间区间重叠计算、Z 字形变换规律推导、外观数列生成逻辑以及青蛙叫声状态机模拟。重点在于细节把控与数学规律挖掘,提供可直接运行的优化代码及复杂度分析,帮助读者掌握模拟类问题的通用解题思路。

RefactorPro发布于 2026/3/24更新于 2026/10/2599 浏览
Java 模拟算法实战:LeetCode 经典题解

Java 模拟算法实战:LeetCode 经典题解

模拟算法的核心在于严格按照题目描述的规则进行一步步操作。这类问题通常逻辑直观,但容易在边界条件和细节处理上出错。下面我们通过五个典型例题,梳理解题思路与代码实现。

替换所有的问号

题目描述:将字符串 s 中的所有 ? 替换为小写字母,要求替换后的字符不能与其相邻的字符相同。

思路解析:遍历字符串,遇到 ? 时尝试从 a 到 z 寻找一个不与左右邻居冲突的字符即可。这里需要特别注意首尾两个边界情况,即第一个字符只检查右边,最后一个字符只检查左边。

class Solution {
    public String modifyString(String s) {
        int n = s.length();
        char[] chars = s.toCharArray();
        
        for (int i = 0; i < n; i++) {
            if (chars[i] == '?') {
                // 尝试 a-z 找到不重复的字符
                for (char ch = 'a'; ch <= 'z'; ch++) {
                    boolean leftOk = (i == 0 || chars[i - 1] != ch);
                    boolean rightOk = (i == n - 1 || chars[i + 1] != ch);
                    
                    if (leftOk && rightOk) {
                        chars[i] = ch;
                        break;
                    }
                }
            }
        }
        return new (chars);
    }
}
String
  • 时间复杂度:O(n),每个字符最多尝试 26 次。
  • 空间复杂度:O(n),用于存储字符数组。

提莫攻击

题目描述:给定攻击时间序列 timeSeries 和中毒持续时间 duration,计算艾希总共处于中毒状态的时间。

思路解析:这是一个区间合并的问题。如果两次攻击的时间间隔大于等于 duration,说明前一次中毒效果已完全结束;否则,前一次中毒被后一次打断,实际贡献时间为时间差值。最后别忘了加上最后一次攻击的完整持续时间。

class Solution {
    public int findPoisonedDuration(int[] timeSeries, int duration) {
        if (timeSeries == null || timeSeries.length == 0) {
            return 0;
        }
        
        int totalDuration = 0;
        for (int i = 1; i < timeSeries.length; i++) {
            int interval = timeSeries[i] - timeSeries[i - 1];
            // 取时间差和持续时间的较小值
            totalDuration += Math.min(interval, duration);
        }
        // 加上最后一次攻击的完整持续时间
        return totalDuration + duration;
    }
}
  • 时间复杂度:O(n)
  • 空间复杂度:O(1)

Z 字形变换

题目描述:将字符串按照 Z 字形排列在指定行数中,然后按行读取生成新字符串。

思路解析:直接构建二维矩阵会消耗过多空间。观察规律可知,字符的行号变化呈现周期性(从上到下再从上到下)。我们可以利用数学公式直接计算每个字符应该归属的行,或者通过模拟行指针的移动来填充结果。

class Solution {
    public String convert(String s, int numRows) {
        if (numRows < 2) {
            return s;
        }
        
        int n = s.length();
        int cycleLen = 2 * numRows - 2;
        StringBuilder sb = new StringBuilder();
        
        // 第一行
        for (int i = 0; i < n; i += cycleLen) {
            sb.append(s.charAt(i));
        }
        
        // 中间行
        for (int row = 1; row < numRows - 1; row++) {
            for (int i = 0; i < n; i += cycleLen) {
                if (i + row < n) {
                    sb.append(s.charAt(i + row));
                }
                if (i + cycleLen - row < n) {
                    sb.append(s.charAt(i + cycleLen - row));
                }
            }
        }
        
        // 最后一行
        for (int i = numRows - 1; i < n; i += cycleLen) {
            sb.append(s.charAt(i));
        }
        
        return sb.toString();
    }
}
  • 时间复杂度:O(n)
  • 空间复杂度:O(n)

外观数列

题目描述:第 n 项是对第 n-1 项的描述,例如 "1" -> "11" -> "21"...

思路解析:使用双指针遍历当前字符串。左指针标记当前数字的起始位置,右指针向右移动直到遇到不同字符。统计连续相同字符的数量,拼接数量和新字符作为下一行的内容。

class Solution {
    public String countAndSay(int n) {
        String result = "1";
        
        for (int i = 1; i < n; i++) {
            StringBuilder sb = new StringBuilder();
            int len = result.length();
            int left = 0, right = 0;
            
            while (right < len) {
                while (right < len && result.charAt(left) == result.charAt(right)) {
                    right++;
                }
                sb.append(right - left).append(result.charAt(left));
                left = right;
            }
            result = sb.toString();
        }
        return result;
    }
}

数青蛙

题目描述:给定字符串 croakOfFrogs,求最少需要多少只青蛙才能发出这些叫声。如果字符串无效则返回 -1。

思路解析:这本质上是一个状态机问题。每只青蛙必须按顺序发出 c->r->o->a->k。我们需要跟踪每种字符出现的次数。当遇到 c 时,优先复用已经叫完 k 的青蛙;遇到其他字符时,必须确保其前驱字符有可用的青蛙。最终所有青蛙都必须完成叫声(即 k 的数量等于其他字符数量)。

class Solution {
    public int minNumberOfFrogs(String croakOfFrogs) {
        if (croakOfFrogs.length() % 5 != 0) {
            return -1;
        }
        
        int c = 0, r = 0, o = 0, a = 0, k = 0;
        int maxFrogs = 0;
        
        for (char ch : croakOfFrogs.toCharArray()) {
            switch (ch) {
                case 'c':
                    if (k > 0) k--;
                    else maxFrogs++;
                    c++;
                    break;
                case 'r':
                    if (c == 0) return -1;
                    c--; r++;
                    break;
                case 'o':
                    if (r == 0) return -1;
                    r--; o++;
                    break;
                case 'a':
                    if (o == 0) return -1;
                    o--; a++;
                    break;
                case 'k':
                    if (a == 0) return -1;
                    a--; k++;
                    break;
            }
        }
        
        return (c == 0 && r == 0 && o == 0 && a == 0) ? maxFrogs : -1;
    }
}
  • 时间复杂度:O(n)
  • 空间复杂度:O(1)

目录

  1. Java 模拟算法实战:LeetCode 经典题解
  2. 替换所有的问号
  3. 提莫攻击
  4. Z 字形变换
  5. 外观数列
  6. 数青蛙

更多推荐文章

查看全部
  • AI 编程工具深度对比:Cursor、Copilot、Trae 与 Claude Code
  • pxcharts-vue:基于 Vue3 的开源多维表格解决方案
  • 基于 Unity 和 AI 零代码制作小游戏“飞翔的牛马”
  • 数据结构:双向链表实现与算法分析
  • 大模型产品经理转型指南:从零开始的全面路径
  • AI 时代打造超级个体:个人效能提升与实战路径
  • JavaScript 对象与数组核心用法
  • 阿里云 DashScope、OpenAI 及 aiohttp Python SDK 异步性能对比
  • Prometheus + Grafana 实现 Java 应用数据监控系统
  • Vue3 + TypeScript Promise 转 string 类型错误解析及异步处理最佳实践
  • 机器人底盘无刷电机 PWM 调速板驱动 75mm 麦克纳姆轮
  • 基于 Vue 和 Python 的校园互助交友平台设计与实现
  • AirSim 无人机仿真平台:环境搭建与实战应用
  • AI+AR智能眼镜赛道年终观察
  • llama.cpp 核心特性、技术原理与实用部署
  • LeetCode 92 链表区间反转:递归反转与哨兵技巧
  • C++ 二叉搜索树:从基础概念到代码实现
  • C++ 笔试刷题:排序子序列、消减整数与最长上升子序列
  • 华为 OD 机试双机位 C 卷:挑选宝石
  • Python act-atmos 大气数据处理工具包介绍

相关免费在线工具

  • Keycode 信息

    查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online

  • Escape 与 Native 编解码

    JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online

  • JavaScript / HTML 格式化

    使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online

  • JavaScript 压缩与混淆

    Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online

  • 加密/解密文本

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

  • Gemini 图片去水印

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