Question
A message containing letters from A-Z
is being encoded to numbers using the following mapping:
'A' -> 1
'B' -> 2
...
'Z' -> 26
Given an encoded message containing digits, determine the total number of ways to decode it.
For example,
Given encoded message "12"
, it could be decoded as "AB"
(1 2) or "L"
(12).
The number of ways decoding "12"
is 2.
本题难度Medium。
DP
【复杂度】
时间 O(N) 空间 O(N)
【思路】
这道题有点像[LeetCode]Climbing Stairs,但比它复杂点。我本来是用dfs来做的,简单直观但是超时。对于这种数组问题,剩下的可选方案也就是DP了。
假设数组元素dp[i]
表示从头到字符串的第i位一共有多少种解码方法的话,那么如果字符串的第i位不为'0'
,就可以在第i-1位的基础上继续解码,dp[i]+=dp[i-1];
;如果字符串的第i-1位和第i位能组成一个10到26的数字,说明我们可以在第i-2位的解码方法上继续解码,dp[i]+=dp[i-2];
。这里要清楚不是0到26,对于类似于"02"
这样的是被判定为不可解码的。
【附】
这里有个技巧:
dp[i]
并不对应s的第i个字符,而是对应于s的第i-1个字符,有点像链表中的fake节点功能。令dp[0]=1;
而dp[1]=s.charAt(0)=='0'?0:1;
,这样就可以应对"20"
这样的情况:
【注意】
如果字串的长度为0,要返回0。(代码5-6行)
【代码】
public class Solution {
public int numDecodings(String s) {
//require
int size=s.length();
if(size<1)
return 0;
int[] dp=new int[size+1];
dp[0]=1;
dp[1]=s.charAt(0)=='0'?0:1;
//invariant
for(int i=2;i<=size;i++){
dp[i]+=s.charAt(i-1)=='0'?0:dp[i-1];
int tmp=Integer.parseInt(s.substring(i-2,i));
dp[i]+=(10<=tmp&&tmp<=26)?dp[i-2]:0;
}
//ensure
return dp[size];
}
}
参考
[Leetcode] Decode Ways 解码方式