91. Decode Ways

题目:

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.

链接: http://leetcode.com/problems/decode-ways/

题解:

一看到这题就想到了爬楼梯climb stairs,典型的一维DP。下面就用一维DP来做。先建立数组dp = new int[s.length() + 1], 初始化一个数字的情况dp[0] = 1, 两个数字组成一个两位数字的情况dp[1] = 1。接下来写出循环体,先算一个数字的情况,当s.charAt(i - 1)不为0的时候,dp[i] = dp[i - 1], 否则dp[i] = 0。 接下来考虑两位数字,当由i-2和i-1这两位组成的数字大于等于10,小于等于26时,dp[i] += dp[i - 2], 否则忽略此种情况。

Time Complexity - O(n), Space Complexity - O(n)。

public class Solution {
public int numDecodings(String s) {
if(s == null || s.length() == 0 || s.charAt(0) == '0')
return 0;
int[] dp = new int[s.length() + 1];
dp[0] = 1;
dp[1] = 1; for(int i = 2; i < dp.length; i++) {
int num = Integer.parseInt(s.substring(i - 2, i));
int twoStepsBehind = (num <= 26 && num >= 10) ? dp[i - 2] : 0;
int oneStepBehind = s.charAt(i - 1) != '0' ? dp[i - 1] : 0;
dp[i] = twoStepsBehind + oneStepBehind;
} return dp[s.length()];
}
}

可以继续优化Space Complexity至O(1).

public class Solution {
public int numDecodings(String s) {
if(s == null || s.length() == 0 || s.charAt(0) == '0')
return 0; int first = 1;
int second = 1; for(int i = 2; i < s.length() + 1; i++) {
int num = Integer.parseInt(s.substring(i - 2, i));
int twoStepsBehind = (num >= 10 && num <= 26) ? first : 0;
int oneStepBehind = s.charAt(i - 1) != '0' ? second : 0;
first = second;
second = twoStepsBehind + oneStepBehind;
} return second;
}
}

题外话: 使用DP思想的一些题目 - decode ways, climb stairs, find LCS(longest common subsequence), find longest ascending subsequence, fine longest descending subsequens, 背包问题,poj滑雪,等等。DP这种重要的编程思想要好好学习领会。

二刷:

还是使用dp,新建一个dp数组比较好理解,但空间的优化却不是很熟练。对于dp,还是需要加强狠练。如何才能写出优雅而且精炼的代码是个问题。 Elegant and concise

Java:

Time Complexity - O(n), Space Complexity - O(n)。

public class Solution {
public int numDecodings(String s) {
if (s == null || s.length() == 0 || s.charAt(0) == '0') {
return 0;
}
int len = s.length();
int[] numWays = new int[len + 1];
numWays[0] = 1; // empty string
numWays[1] = 1; // one char
for (int i = 2; i <= len; i++) {
int num = Integer.parseInt(s.substring(i - 2, i));
numWays[i] = (num <= 26 && num >= 10) ? numWays[i - 2] : 0;
numWays[i] += (s.charAt(i - 1) != '0') ? numWays[i - 1] : 0;
}
return numWays[len];
}
}

因为do[i] 只和dp[i - 1]以及dp[i - 2]有关,我们可以优化空间到O(1)。就是使用两个变量来代表numWays[i - 1]和numWays[i - 2], 以及一个变量res来代表它们的和,接下来三个一起倒腾倒腾就好了

Time Complexity - O(n), Space Complexity - O(1)。

public class Solution {
public int numDecodings(String s) {
if (s == null || s.length() == 0 || s.charAt(0) == '0') {
return 0;
}
int len = s.length();
int lastTwoSteps = 1; // empty string
int lastOneStep = 1; // one char
int res = 0;
for (int i = 2; i <= len; i++) {
int num = Integer.parseInt(s.substring(i - 2, i));
res += (num <= 26 && num >= 10) ? lastTwoSteps : 0;
res += (s.charAt(i - 1) != '0') ? lastOneStep : 0;
lastTwoSteps = lastOneStep;
lastOneStep = res;
res = 0;
}
return lastOneStep;
}
}

题外话:

2/11/2016:

时间相当紧张,要复习LC,刷面经,多线程,设计模式,系统设计。自己提速却不是很成功,转进努力吧。要深入思考。

自己与去年9月开始刷题以来,有什么改变和进步呢??? 好像并没有实质性的突破....要说进步的地方,可能就是养成了学习的习惯吧

Reference:

https://leetcode.com/discuss/49719/dp-with-easy-understand-java-solution

https://leetcode.com/discuss/8527/dp-solution-java-for-reference

上一篇:ActionScript3.0(AS3)中的泛型数组Vector


下一篇:Sublime Text 3 全程详细图文原创教程(持续更新中。。。)