当前位置: 首页 > 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),是更优的解决方案。

http://www.lqws.cn/news/502759.html

相关文章:

  • Kafka 监控与调优实战指南(二)
  • Matplotlib vs Seaborn:选择与区别
  • 逆向入门(7)汇编篇-mul指令的学习
  • GitLab 备份恢复与配置迁移详尽教程(实战版)
  • 创客匠人拆解知识变现从 IP 到商业闭环的关键要素
  • 基于版本控制+WORM的OSS数据保护:防勒索攻击与法规遵从实践
  • OpenCV CUDA模块设备层-----检查 CUDA 错误并输出调试信息内联函数checkCudaError()
  • 【Linux网络编程】多路转接I/O(一)select,poll
  • HTML炫酷烟花
  • ✨从零搭建 Ubuntu22.04 + Python3.11 + PyTorch2.5.1 GPU Docker 镜像并上传 Docker Hub
  • Flask(二) 路由routes
  • 零知开源——STM32F4实现ILI9486显示屏UI界面系列教程(三):记事本功能实现
  • bmc TrueSight 监控mysql配置
  • prometheus+grafana+Linux监控
  • Linux 中的信号处理方式详解
  • 【机器学习深度学习】多层神经网络的构成
  • 在仓颉开发语言中使用数据库
  • TCP/UDP协议深度解析(一):UDP特性与TCP确认应答以及重传机制
  • 计算机网络第九章——数据链路层《介质访问控制》
  • C++(面向对象编程——多态)
  • 曼昆《经济学原理》第九版 宏观经济学 第二十六章货币增长与通货膨胀
  • python中学物理实验模拟:摩檫力
  • BI财务分析 – 反映盈利水平利润占比的指标如何分析(下)
  • iwebsec靶场sqli注入(2)
  • [Linux] Linux用户和组管理
  • GoAdmin代码生成器实践
  • 大模型项目实战:业务场景和解决方案
  • TongWeb替换tomcat
  • Linux Sonic Agent 端部署(详细版)(腾讯云)
  • MySQL:深入总结锁机制