算法43,外观数列,模拟算法+双指针

题目:38. 外观数列(Count and Say)

题目描述:

外观数列是一个整数序列,从数字 1 开始。后续每一项都是对前一项的描述(报数)。

  • n = 1 时,输出 "1"
  • n = 2 时,描述前一项 "1"(1个1),输出 "11"
  • n = 3 时,描述前一项 "11"(2个1),输出 "21"
  • n = 4 时,描述前一项 "21"(1个2,1个1),输出 "1211"

算法原理

  1. 外层循环(迭代生成) :从 i = 1 开始遍历到 n-1,每次根据当前的字符串 ret 生成下一项。
  2. 内层双指针(统计连续字符) :
    • 使用 left 和 right 两个指针。
    • right 不断向右移动,直到遇到与 left 不同的字符或到达字符串末尾。
    • 此时 right - left 就是连续相同字符的个数。
    • 将个数 和字符 依次追加到临时容器中,然后让 left = right,继续下一组统计。
  3. 类型转换 :利用 StringBuilder 高效拼接字符串,生成新项后转为 String 赋值给 ret。

解题模拟(以 n = 4 为例)

步骤 当前 ret 值 双指针统计过程 生成的 tmp 值
初始 "1" - -
i=1 "1" 统计到 1 个 '1' "11"
i=2 "11" 统计到 2 个 '1' "21"
i=3 "21" 统计到 1 个 '2',1 个 '1' "1211"
结束 "1211" 返回结果 -

代码答案

复制代码
class Solution {
    public String countAndSay(int n) {
        String ret = "1";
        for (int i = 1; i < n; i++) {
            StringBuilder tmp = new StringBuilder();
            int len = ret.length();
            for (int left = 0, right = 0; right < len; ) {
                // 重点:right < len 必须放在前面防止越界
                while (right < len && ret.charAt(left) == ret.charAt(right)) {
                    right++;
                }
                tmp.append(Integer.toString(right - left)); // 追加数量
                tmp.append(ret.charAt(left));             // 追加字符
                left = right;
            }
            ret = tmp.toString(); // StringBuilder 转为 String
        }
        return ret;
    }
}

知识点总结:String、StringBuilder 与数组对比

特性维度 数组 (Array) String (字符串) StringBuilder (可变字符串)
可变性​ 可变(修改元素原地生效) 不可变(修改会生成新对象) 可变(原地修改,性能好)
取值方式​ arr[index] charAt(index) 无直接下标取值法
长度获取​ arr.length (属性) str.length() (方法) sb.length() (方法)
追加/修改​ arr[index] = val 不能用 + 频繁拼接 append(数据) 追加到末尾
类型转换​ - Integer.toString(数字) sb.toString() 转为 String
适用场景​ 固定长度数据存储 最终稳定结果、只读场景 循环内频繁拼接/修改字符串

核心避坑指南:

  1. while 循环判断边界时,right < len 必须写在前面 (利用 Java 的短路与 && 特性),否则会触发 StringIndexOutOfBoundsException。
  2. String 和 StringBuilder 类型不兼容,赋值时必须用 toString() 显式转换。
相关推荐
通信小呆呆8 小时前
电子战抗干扰技术:当“不被干扰”成为一种系统
算法·通信·mimo·isac
笑容掩饰我的失落8 小时前
区块链从小白到精通(八):从零实现一个标准 ERC-20 代币(完整可运行代码)
算法·区块链·php·智能合约·哈希算法
学长毕设9 小时前
基于SpringBoot的景点管理系统-附源码
java·spring boot·后端
Severus_black9 小时前
【C++初阶】Stack、Queue算法题大练兵!
c语言·c++·算法·stl
sxlishaobin10 小时前
Maven Setting详解
java·学习·maven
知守观10 小时前
一个方法两个触发口:反编译 XXL-Job 后,我看清了 inner/job 子包的裸奔现状
java·spring boot·微服务
用户31268748772010 小时前
CompletableFuture 链式编排:异步编程的优雅解法
java
瑞雪兆丰年兮10 小时前
JavaWeb-day14-SpringBootWeb原理篇
java·开发语言·spring boot·spring·bean·mybatis·javaweb
神仙别闹10 小时前
基于 Java GUI 贪心策略直接搜索算法和极大极小博弈树算法的智能人机博弈五子棋游戏
java·毕业设计·gui·贪心策略·极大极小博弈树
Flynn Liang11 小时前
RAG 评估体系:黄金集、检索指标与 LLM-as-Judge 落地
java·langchain·rag·评估·langchain4j·检索指标