• 剑指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
    }
    
    心之所向,素履以往
  • 相关阅读:
    前端开发规范:命名规范、html 规范、css 规范、js 规范
    node.js入门系列(一)--Node.js简介
    浅析前端开发中的 MVC/MVP/MVVM 模式
    网页加载进度条的实现
    JavaScript深入系列(一)--原型和原型链详解
    vue2.0项目实战(5)vuex快速入门
    既然写CSS很容易,那为什么大家还是把CSS写的那么烂呢?
    vue2.0项目实战(4)生命周期和钩子函数详解
    vue2.0项目实战(3)使用axios发送请求
    【css技能提升】完美的 Sticky Footer 布局
  • 原文地址:https://www.cnblogs.com/yinbiao/p/15739667.html
Copyright © 2020-2023  润新知