天天一道Rust-LeetCode(2019-06-08)

天天一道Rust-LeetCode(2019-06-08) 91. 解碼方法

堅持天天一道題,刷題學習Rust.git

題目描述

https://leetcode-cn.com/problems/decode-ways/github

一條包含字母 A-Z 的消息經過如下方式進行了編碼:學習

'A' -> 1
'B' -> 2
...
'Z' -> 26
給定一個只包含數字的非空字符串,請計算解碼方法的總數。編碼

示例 1:code

輸入: "12"
輸出: 2
解釋: 它能夠解碼爲 "AB"(1 2)或者 "L"(12)。
示例 2:ci

輸入: "226"
輸出: 3
解釋: 它能夠解碼爲 "BZ" (2 26), "VF" (22 6), 或者 "BBF" (2 2 6) 。leetcode

解題過程

思路:
由於根據編號,只有連續兩位的而且不超過26的纔是有效的編碼,
長度爲N的解碼方法:
a[0...N-1]={a[0...N-2] +a[N-1]}+{a[0...N-3]+a[n-2,n-1]}
若是後一種狀況a[n-2,n-1]範圍在26以內的話.
有點相似於斐波那契數列求解的過程字符串

struct Solution {}
impl Solution {
    pub fn num_decodings(s: String) -> i32 {
        Solution::decodings(&s.as_bytes().iter().map(|i| i - ('0' as u8)).collect())
    }
    fn decodings(v: &Vec<u8>) -> i32 {
        if v.len() <= 0 {
            return 0;
        }
        let mut vcnt = Vec::with_capacity(v.len());
        if v[0] == 0 {
            return 0;
        }
        vcnt.push(1); //只有一個字符的時候確定是只有一種編碼
        for i in 1..v.len() {
            let mut cnt = 0;
            if v[i] != 0 {
                //只要不是0的數字,都是有效的編碼
                cnt = vcnt[i - 1]; //第一種分法
            }
            if i >= 1 {
                //考慮 i-1,i聯合起來的情形
                let n = v[i - 1] * 10 + v[i];
                if (v[i - 1] == 1 || v[i - 1] == 2) && n <= 26 {
                    //有效編碼
                    if i >= 2 {
                        cnt += vcnt[i - 2];
                    } else {
                        cnt += 1; //考慮到只有兩個字符,這時候下標就出界了.
                    }
                } else if n == 0 {
                    return 0; //連續的兩個數字0,是不可能被編碼的,後續的也無效了
                } else {
                    //超過的,不能有效編碼,可是輸入是合法的.
                }
            }
            vcnt.push(cnt);
        }
        vcnt[v.len() - 1]
    }
}
#[cfg(test)]
mod test {
    use super::*;
    #[test]
    fn test_decodings() {
        assert_eq!(2, Solution::num_decodings(String::from("12")));
        assert_eq!(0, Solution::num_decodings(String::from("")));
        assert_eq!(0, Solution::num_decodings(String::from("0")));
        assert_eq!(1, Solution::num_decodings(String::from("10")));
        assert_eq!(1, Solution::num_decodings(String::from("101")));
        assert_eq!(0, Solution::num_decodings(String::from("100")));
        assert_eq!(1, Solution::num_decodings(String::from("1")));
        assert_eq!(3, Solution::num_decodings(String::from("226")));
        assert_eq!(2, Solution::num_decodings(String::from("227")));
    }
}

一點感悟

這個題目很簡單,可是在處理0的時候被坑了幾回,
一開始沒注意0這種狀況
可是後來又考慮的比較簡單,因此錯了幾回.
主要有如下幾種狀況:get

  1. 非法輸入
    開頭的0,連續的00,都沒法有效解碼
  2. 中間出現的0,
    10是合法的,30不合法,101注意不知足第二種拆分狀況,由於01不是有效編碼it

    其餘

歡迎關注個人github,本項目文章全部代碼均可以找到.

相關文章
相關標籤/搜索