劍指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
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章