(Version 0.0)
Decode Ways这道题从原理上说是一个比较简单的一维DP题目,用一个一维数组的元素dp[i] (i >= 1)来记录从头开始长度为i的substring有多少种decode ways。
不过实际操作起来第一次写还是在输入为"0"时犯了错误,另外第一次写的时候没有意识到当可以构成"10"和"20"时dp[i]要等于dp[i - 2],而不能取dp[i - 1] + dp[i - 2],另外一个易错点是对于dp[0]的初始化,应该为1而不是0。整体感觉这题只要是有DP的思维就不难,但是要考虑清楚各种情况的取舍以及corner case。代码如下:
1 public class Solution { 2 public int numDecodings(String s) { 3 if (s.length() < 2) { 4 return s.equals("0") ? 0 : s.length(); // don't forget to check if s is "0" 5 } 6 int[] dp = new int[s.length() + 1]; 7 dp[0] = 1; // be careful with this initialization 8 dp[1] = s.charAt(0) == '0' ? 0 : 1; 9 for (int i = 2; i < dp.length; i++) { 10 int val = Integer.valueOf(s.substring(i - 2, i)); 11 if (val == 0) { 12 return 0; 13 } else if (val <= 9) { 14 dp[i] = dp[i - 1]; 15 } else if (val < 27) { 16 if (val % 10 == 0) { 17 dp[i] = dp[i - 2]; 18 } else { 19 dp[i] = dp[i - 1] + dp[i - 2]; 20 } 21 } else { 22 if (val % 10 == 0) { 23 return 0; 24 } else { 25 dp[i] = dp[i - 1]; 26 } 27 } 28 } 29 return dp[dp.length - 1]; 30 } 31 }
循环内的思路大致是,如果当前char不能和前一个char组成合法数字时,dp[i] = dp[i - 1];如果当前char为0且前一个也为0或者前一个char大于2,则此decoding invalid,可以直接返回0;如果当前char可以和前一个char组成合法数字,则需要把前两个dp中的元素相加作为当前元素的值,因为在之前的子串上加上当前char可以增添两种可能性,即与前一个char结合或者不结合,如果结合,则有dp[i - 2]种,不结合则有dp[i - 1]种,所以总共是dp[i - 1] + dp[i - 2]种。