zoukankan      html  css  js  c++  java
  • [LeetCode#91]Decode Ways

    Problem:

    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.

    Analysis:

    Note the transitional function!!!
    At first glance, it could be solved through recursive call. But we only care about the total count!!! Why we must follow that routinue.
    The difference here are only: count the present digit as a character, or count two digits as a character. For all chacter, we should ask us the same question. since there are only two possible situations, why not we use dynamic programming for it.
    The range of two digits in this problem is '00' - '99', we could intepret those two digits separately or together. 
    Suppose res[i] represents the sequences count from 0 to i.
    1.'00'
    res[i] = 0, since '00' is invalid and '0' is invalid.
    
    2. '01' - '09'
    res[i] = res[i-1], must be sperated.
    
    3. '10', '20'
    res[i] = res[i-2], the new added character must be combined with '1' or '2'
    
    4. '11-19', '21 - 26'
    res[i] = res[i-2] + res[i-1]
    
    5. '27-99' not include *0
    res[i] = res[i-1]
    
    ----------------------------------------------------
    1.'00'
    res[i] = 0, since '00' is invalid and '0' is invalid.
    ----------------------------------------------------
    6. *0 (exclude '10', '20')
    res[i] = 0
    
    Do you think the above analysis is too ugly and complex?
    When a '0' appears, we need to tackle so many different cases. The related program must be very ugly too!
    
    Can we find a way to avoid the complex checking?
    Yes!!!!
    Why not do the dynamic prgramming from right to left?
    
    '0*' must be invalid for both cases, we can directly ignore it.
    '01'. '0'is invalid, and '01' is also invalid. 
    for (int i = len-1; i >= 0; i--) {
        if (s.charAt(i) != '0') {
            ...
    }
    
    If s.charAt(i) is not equal to '0', 
    1. it must could be separately intepreted '1' .. '9' are valid.
    2. it might be valid for inteprrting together. '11' _ '26' are valid. (note: no '0' start)
    if (s.charAt(i) != '0') {
        dp[i] = dp[i+1];
        if (i < len-1 && Integer.parseInt(s.substring(i, i+2)) <= 26)
            dp[i] += dp[i+2];
    }
    
    How easy of this solution, right?
    Skills:
    How initiate the value for first intepreted character or 'two character'.
    Can you use 
    int[] dp = new int[len];
    dp[0] = 1
    Absolutely no!!!, what if the last character is '0'. like '20'
    And it would break the elegant code structure. 
    
    How about use a extra element?
    int[] dp = new int[len+1];
    dp[len] = 1;
    
    1. last character
    if the last element is '0'. 
    dp[len-1] still equal to 0
    if the last element is not '0'.
    dp[i] = dp[i+1];
    
    2. last two character
    if the second to last element is '0'
    dp[len-1] still equal to 0
    if the second to last element is not '0' and in the valid range '11 - 26'
    dp[i] += dp[i+2] (1);
    
    
    What a great skill!!!
    How to give the initial value for two case through a additional element, while keep the elegant code structure at the same time.

    Solution:

    public class Solution {
        public int numDecodings(String s) {
            if (s == null || s.length() == 0)
                return 0;
            int len = s.length();
            int[] dp = new int[len+1];
            dp[len] = 1;
            for (int i = len-1; i >= 0; i--) {
                if (s.charAt(i) != '0') {
                    dp[i] = dp[i+1];
                    if (i < len-1 && Integer.parseInt(s.substring(i, i+2)) <= 26)
                        dp[i] += dp[i+2];
                }
            }
            return dp[0];
        }
    }
  • 相关阅读:
    4-vim-工作模式-01-职责以及切换模式
    3-vim-打开和新建文件-02-删除交换文件
    poj1011Stick(dfs+剪枝)
    POJ 1251 Jungle Roads (prim)
    poj 2502 Subway
    poj 3624 Charm Bracelet (01背包)
    拦截导弹问题(动态规划)
    Policy Gradient
    深入了解马尔科夫决策过程(Markov Decision Process)
    深度学习中调参对模型容量的影响
  • 原文地址:https://www.cnblogs.com/airwindow/p/4762412.html
Copyright © 2011-2022 走看看