zoukankan      html  css  js  c++  java
  • 剑指offer把数字翻译成字符串(dp)

    给定一个数字,我们按照如下规则把它翻译为字符串:0 翻译成 “a” ,1 翻译成 “b”,……,11 翻译成 “l”,……,25 翻译成 “z”。一个数字可能有多个翻译。请编程实现一个函数,用来计算一个数字有多少种不同的翻译方法。

    示例 1:

    输入: 12258
    输出: 5
    解释: 12258有5种不同的翻译,分别是"bccfi", "bwfi", "bczi", "mcfi"和"mzi"

    提示:

    0 <= num < 231

    来源:力扣(LeetCode)
    链接:https://leetcode-cn.com/problems/ba-shu-zi-fan-yi-cheng-zi-fu-chuan-lcof

    分析:
    动态规划
    dp[n-1]代表截止到下标为n-1的字符,其方案数
    对下标为i的字符来说,其方案数其实取决于前面字符的方案数,是前面字符的状态转移,所以可以对当前字符和前一个字符讨论,得到其状态转移方程
    如果str[i]和str[i-1]可以组成一个字符,则dp[i]=dp[i-2]+dp[i-1]
    如果str[i]和str[i-1]不能组成一个字符,则dp[i]=dp[i-1]
    以12258为例
    字符: 1 2 2 5 8
    方案: 1 2 3 5 5
    i=0方案:1种
    1
    i=1的方案:2种
    1 2
    12

    i的方案:(取决于i和i-1能否组成新字符串)
    假设i=2,其方案如下:
    1 22 =====> i-2的方案+后面加新组成的字符串

    1 2 2 =====> i-1的方案+后面str[i]字符
    12 2

    假设i=3,其方案如下:
    1 2 25 =====> i-2的方案+后面加新组成的字符串
    12 25

    1 22 5 =====> i-1的方案+后面str[i]字符
    1 2 2 5
    12 2 5

    假设i=4,str[i]和str[i-1]值为58,不能组成新的字符
    所有其方案数等于i-1的方案数量
    1 2 25 8
    12 25 8

    1 22 5 8
    1 2 2 5 8
    12 2 5 8
    就是i-1的所有方案,后面加一个字符8,其总的方案数量还是没有变的

    当前方法是时间复杂度为O(N),如果用额外的dp数组记录,则其空间复杂度为O(N),但是每次计算只依赖于前面两项,可以采取滚动计数的形式,这样空间复杂度可以简化到O(1)

    1.dp数组记录
    时间复杂度:O(N)
    空间复杂度:O(N)

    func translateNum(num int) int {
    	str := strconv.Itoa(num)
    	n := len(str)
    
    	var dp [105]int
    	dp[0]=1
    	if n==1{
    		return dp[0]
    	}
    	temp,_:=strconv.ParseInt(str[0:2],10,64)
    	if temp>=10&&temp<=25{
    		dp[1]=2
    	}else {
    		dp[1]=1
    	}
    
    	for i := 2; i < n; i++ {
    		temp, _ := strconv.ParseInt(str[i-1:i+1], 10, 64)
    		if temp >= 10 && temp <= 25 {
    			dp[i] = dp[i-1] + dp[i-2]
    		} else {
    			dp[i] = dp[i-1]
    		}
    	}
    	return dp[n-1]
    }
    

    2.滚动计数
    时间复杂度:O(N)
    空间复杂度:O(1)

    func translateNum(num int) int {
    	str := strconv.Itoa(num)
    	n := len(str)
    
    	var k1,k2,k3 int
    	k1=1
    	if n==1{
    		return k1
    	}
    	temp,_:=strconv.ParseInt(str[0:2],10,64)
    	if temp>=10&&temp<=25{
    		k2=2
    	}else {
    		k2=1
    	}
    
    	if n==2{
    		return k2
    	}
    
    	for i := 2; i < n; i++ {
    		temp, _ := strconv.ParseInt(str[i-1:i+1], 10, 64)
    		if temp >= 10 && temp <= 25 {
    			k3=k2+k1
    		} else {
    			k3=k2
    		}
    		k1=k2
    		k2=k3
    	}
    	return k3
    }
    
    心之所向,素履以往
  • 相关阅读:
    面试题来积累自己
    基于php基础语言编写的小程序之计算器
    配置apache的虚拟机+软件下载
    执行表空间使用率SQL突然变慢问题分析
    DM-建库选项-字符串比较大小写敏感-测试
    OGG再次遇到虚拟列无法处理,导致进程abend二
    OGG应用进程abend报错无法insert虚拟列
    Oracle Asm Failgroup测试学习
    OGG复制进程报错,存在update set 主键列 is null
    测试:OGG初始化同步表,源端抽取进程scn<源端事务的start_scn时,这个变化是否会同步到目标库中?
  • 原文地址:https://www.cnblogs.com/yinbiao/p/15739667.html
Copyright © 2011-2022 走看看