当前位置: 首页 > news >正文

左神算法之数字字符串解码方案计数算法

文章目录

  • 数字解码为字母的方案计数
    • 问题理解
    • 解题思路
    • Java实现
    • 代码解析
    • 测试用例
    • 总结

数字解码为字母的方案计数

问题理解

给定一个数字字符串,我们需要计算它可以被解码为字母字符串的所有可能方式。解码规则为:

  • 数字1对应字母’a’
  • 数字2对应字母’b’
  • 数字26对应字母’z’

例如,"12258"有5种解码方式:

  1. 1 2 2 5 8 → “abbeh”
  2. 1 2 25 8 → “abyh”
  3. 1 22 5 8 → “aveh”
  4. 12 2 5 8 → “lbeh”
  5. 12 25 8 → “lyh”

解题思路

这个问题可以使用动态规划来解决,关键在于如何处理数字的组合方式:

  1. 基本情况

    • 空字符串有1种解码方式(即空字符串)
    • 单个数字字符(非’0’)有1种解码方式
  2. 递推关系

    • 当前数字可以单独解码(1-9)
    • 当前数字和前一个数字可以组合解码(10-26)
  3. 边界条件

    • 数字’0’不能单独解码
    • 以’0’开头的字符串无法解码

Java实现

public class DecodeWays {public static int numDecodings(String s) {if (s == null || s.length() == 0) {return 0;}int n = s.length();int[] dp = new int[n + 1];dp[0] = 1; // 空字符串有1种解码方式dp[1] = s.charAt(0) == '0' ? 0 : 1; // 第一个字符的解码方式for (int i = 2; i <= n; i++) {// 检查单个数字int oneDigit = Integer.parseInt(s.substring(i - 1, i));if (oneDigit >= 1 && oneDigit <= 9) {dp[i] += dp[i - 1];}// 检查两个数字组合int twoDigits = Integer.parseInt(s.substring(i - 2, i));if (twoDigits >= 10 && twoDigits <= 26) {dp[i] += dp[i - 2];}}return dp[n];}// 优化空间版本public static int numDecodingsOptimized(String s) {if (s == null || s.length() == 0 || s.charAt(0) == '0') {return 0;}int prev1 = 1; // dp[i-1]int prev2 = 1; // dp[i-2]for (int i = 1; i < s.length(); i++) {int current = 0;// 检查单个数字if (s.charAt(i) != '0') {current += prev1;}// 检查两个数字组合int twoDigits = Integer.parseInt(s.substring(i - 1, i + 1));if (twoDigits >= 10 && twoDigits <= 26) {current += prev2;}prev2 = prev1;prev1 = current;}return prev1;}public static void main(String[] args) {System.out.println(numDecodings("12258")); // 输出5System.out.println(numDecodings("226"));   // 输出3System.out.println(numDecodings("06"));    // 输出0System.out.println(numDecodingsOptimized("12258")); // 输出5System.out.println(numDecodingsOptimized("226"));   // 输出3System.out.println(numDecodingsOptimized("06"));    // 输出0}
}

代码解析

  1. 基础动态规划版本

    • 使用dp数组存储中间结果,dp[i]表示前i个字符的解码方式数
    • 检查单个数字(1-9)和两个数字组合(10-26)的可能性
    • 时间复杂度O(n),空间复杂度O(n)
  2. 优化空间版本

    • 仅使用两个变量prev1prev2代替整个dp数组
    • 每次迭代更新当前值并滚动更新前两个状态
    • 时间复杂度O(n),空间复杂度O(1)

测试用例

public static void main(String[] args) {// 常规测试System.out.println(numDecodings("12"));     // 输出2 ("AB"或"L")System.out.println(numDecodings("226"));   // 输出3// 边界测试System.out.println(numDecodings("0"));     // 输出0System.out.println(numDecodings("10"));    // 输出1System.out.println(numDecodings("100"));   // 输出0// 大数测试System.out.println(numDecodings("1111111111111111111111111111"));  // 输出317811
}

总结

这个问题展示了动态规划在字符串解码问题中的典型应用。关键点在于:

  1. 识别数字可以单独或组合解码的两种情况
  2. 正确处理’0’的特殊情况
  3. 通过状态转移方程累计所有可能的解码方式

优化版本在保持相同时间复杂度的同时,将空间复杂度从O(n)降低到O(1),是更优的解决方案。

相关文章:

  • 信誉好的购物网站建设小学培训机构
  • 知名开发网站公司简介seo包年服务
  • 线上新媒体电商怎么开店最新seo操作
  • 网站制作 连云港百度指数分析数据
  • 网站要注册为什么网站关键词排名分析
  • 交互式网站开发技术asp企业培训员工培训平台
  • 开篇-认识Gin——Go语言Web框架的性能王者
  • Redis 哨兵模式学习笔记
  • 华为云Flexus+DeepSeek征文 | DeepSeek-V3/R1 商用服务华为云开通指南及使用体验全解析
  • python果蔬种植销售一体化服务系统
  • 对于高考边界的理解以及未来就业层级的学习与思考
  • leetcode114-二叉树展开为链表
  • `docker run -it --rm` 笔记250624
  • 论文笔记(八十六)V-HOP: Visuo-Haptic 6D Object Pose Tracking
  • vue 3 计算器
  • MySql:DDL,增删改查:创建表
  • 【大模型学习】项目练习:套壳DeepSeek
  • 火山 RTC 引擎14 设置CB
  • (LeetCode 面试经典 150 题 )121. 买卖股票的最佳时机 (遍历)
  • 自然语言处理入门
  • 【开源项目】比 PyInstaller 更方便:图形界面打包 Python 脚本的体验
  • 工程优化——WebSocket、WSS(WebSocket Secure)和SSE(Server-Sent Events)通信对比
  • PyEcharts教程(009):PyEcharts绘制水球图
  • 常见网络知识,宽带、路由器
  • 【教学类-89-08】20250624新年篇05——元宵节灯笼2CM黏贴边(倒置和正立数字 )
  • 内存泄漏和内存溢出的区别