1. 程式人生 > >LeetCode第[91]題(Java):Decode Ways(解碼方法數)

LeetCode第[91]題(Java):Decode Ways(解碼方法數)

題目:解碼方法數

難度:Medium

題目內容

A message containing letters from A-Z is being encoded to numbers using the following mapping:

'A' -> 1
'B' -> 2
...
'Z' -> 26

Given a non-empty string containing only digits, determine the total number of ways to decode it.

翻譯

一個包含A-Z字母的訊息被編碼成數字,使用以下對映:

“A” - > 1

“B”- > 2

……

“Z”- > 26

給定一個包含數字的非空字串,確定解碼它的總方法數。

我的思路:一開始想用遞迴但是邊界問題太多,就放棄了。

      single 從0開始(每個陣列單獨解碼),count從1開始,如果s[i-1]s[i]二者組成的數字在(0,26 ] 範圍內,那就count+;

      且遇見0的時候,一開始的單獨編碼就不存在了,且少了一次組合的機會,例如【110】 中【11】和【0】不能組合

        所以此時 single = 0;count - 1

我的程式碼

 1     public int numDecodings(String s) {
2 if (s.isEmpty() || s.charAt(0) == '0') 3 return 0; 4 5 int count = 0; 6 int single = 1; 7 for (int i = 1; i < s.length(); i++) { 8 if (s.charAt(i) == '0'){ 9 count = s.length() > 2 ? count-1 : count; 10 single = 0;
11 } 12 int x = Integer.parseInt(s.substring(i-1, i+1)); 13 if ( x<= 26 && x > 0) { 14 count += 1; 15 } 16 } 17 return (count + single) > 0 ? (count + single) : 0; 18 }

結果214 / 258 test cases passed.

Input:"1212" Output:4 Expected:5

編碼過程中的問題

1、最初 single 和 count 沒有分開計算;

2、第9行,當只有兩個的時候,此時count 不需要 -1 ,例如【10】;

3、這個思路還是有問題的,例如【1212】中少計算了【12】【12】這個組合

答案程式碼

 1 public class Solution {
 2     public int numDecodings(String s) {
 3         int n = s.length();
 4         if (n == 0) return 0;
 5         
 6         int[] memo = new int[n+1];
 7         memo[n]  = 1;
 8         memo[n-1] = s.charAt(n-1) != '0' ? 1 : 0;
 9         
10         for (int i = n - 2; i >= 0; i--)
11             if (s.charAt(i) == '0') continue;
12             else memo[i] = (Integer.parseInt(s.substring(i,i+2))<=26) ? memo[i+1]+memo[i+2] : memo[i+1];
13         
14         return memo[0];
15     }
16 }

答案思路

假設所有的數字都有效,且左右兩兩相鄰數之間也有效(1到26),那麼有如下規律

   numDecodings(s) = numDecodings(s.substring(1)) + numDecodings(s.substring(2)) --------------------------------------------------式(1)

規律顯而易見,斐波那契數列。不過是反過來的(從字串後面往前)

當然,那只是假設,也要考慮特殊情況:

使用一個數組(大小為len+1)從後往前記錄對應的數字“出現”後解碼數的增量

1、當前指標所指字元為0

  此時此字元無法解碼,所以式(1)中的前者就只能為0,後者也為0

  例如【023】,substring(1)——【0】|【23】,截掉的【0】不能解析,所以此組合無效

         substring(2)——【02】|【3】,截掉的【02】不能解析,所以此組合無效

  所以0數字出現後,解碼數的增量為0。

2、當前字元的值是有效的(大於0),但是當前字元與右邊字元組合的數字無效(大於26)

  相當於式(1)中的後者=0

  例如【3212】,substring(1)——【3】|【212】,截掉的【3】能解析,所以其值為【212】的解碼數

         substring(2)——【32】|【12】,截掉的【32】不能解析,所以此組合無效\

遞迴實現:

 1     public int numDecodings(String s) {
 2         if (s.isEmpty()) {
 3             return 1;
 4         }
 5         
 6         if (s.charAt(0) == '0') {
 7             return 0;
 8         } 
 9         
10         if (s.length() == 1)
11             return 1;
12             
13         int sub1 = numDecodings(s.substring(1));
14         int sub2 = 0;
15         
16         if (Integer.parseInt(s.substring(0,2)) <= 26) {
17             sub2 = numDecodings(s.substring(2));
18         }
19         return sub1 + sub2;
20     }

此方法會在最後幾個用例(很長)執行超時。

所以答案採用了迭代的方式進行。

優化:既然是斐波納數列,那麼就能使用雙值迭代的方式取代用一個數組進行記錄

 1     public int numDecodings(String s) {
 2         if (s.isEmpty() || s.charAt(0) == '0') {
 3             return 0;
 4         }
 5         int sub1 = 1;
 6         int sub2 = 1;
 7         for (int i = s.length() - 2; i > -1; i--) {
 8             if (s.charAt(i+1) == '0') {
 9                 sub1 = 0;
10             }
11             if (Integer.parseInt(s.substring(i,i+2)) <= 26) {
12                 sub1 = sub1 + sub2;
13                 sub2 = sub1 - sub2;
14             } else {
15                 sub2 = sub1;
16             }
17         }
18         return sub1;
19     }

第11行其實還可以使用字元進行判斷以降低時間和空間複雜度:

   s.charAt(i) == '1' || s.charAt(i) == '2' && s.charAt(i+1) - '0' <= 6 

相關推薦

LeetCode[91](Java)Decode Ways解碼方法

題目:解碼方法數 難度:Medium 題目內容: A message containing letters from A-Z is being encoded to numbers using the following mapping: 'A' -> 1 'B' -> 2 ... 'Z' -

LeetCode筆記-009palindrome number迴文

題目描述: Determine whether an integer is a palindrome. An integer is a palindrome when it reads the same backward as forward. Exa

Python開發【七篇】面向物件進階篇

上一篇《Python 面向物件(初級篇)》文章介紹了面向物件基本知識: 面向物件是一種程式設計方式,此程式設計方式的實現是基於對 類 和 物件 的使用 類 是一個模板,模板中包裝了多個“函式”供使用(可以講多函式中公用的變數封裝到物件中) 物件,根據模板

十五課資料永續性基於AndroidStudio3.2

當應用程式從使用者輸入建立或捕獲資料時,這些資料僅在應用程式的生命週期內可用。 只要應用程式尚未被執行時殺死,您就只能訪問該資料。 關閉應用程式時,應用程式執行時建立的所有資料都將丟失。 Android為我們提供了多種儲存資料的方式,使其可以比應用程式生命週期更長,並允許我們

十六課應用分發基於AndroidStudio3.2

在某些時候,您可能希望將應用程式分發給廣泛的受眾。 Android應用程式可以非常自由地分發,沒有太多限制:您可以在網站上下載它,甚至可以直接通過電子郵件將應用程式傳送給使用者,但許多開發人員選擇在谷歌等市場上釋出應用程式或亞馬遜最大化範圍。無論您打算如何分發,在向公眾釋出應

PowerBI開發 十四篇DAX 表示式時間+過濾+關係

DAX表示式中包含時間關係(Time Intelligence)相關的函式,用於對日期維度進行累加、同比和環比等分析。PowerBI能夠建立關係,通過過濾器來對影響互動的上下文。 一,時間關係 DAX表示式有兩種方式計算累加和,TOTALxTD()是DATESxTD()的語法糖,使得PowerBI對累加和

LintCode刷指南字串處理C++,Python

題目:兩個字串是變位詞 題目難度:簡單 題目描述: 寫出一個函式 anagram(s, t) 判斷兩個字串是否可以通過改變字母的順序變成一樣的字串。 解題思路: C++:引入雜湊的思維,這道題就迎刃而解了。 C++ Code: class Solution {public:    /**     * @par

五套.java高階架構師2017整理版無加密

百度雲盤連結: https://pan.baidu.com/s/1q_sD3za2PuSnQBoC4NW51w 連結失效,加微信:sun_sha_tan   01-java高階架構師設計-基礎深入等多個檔案 02-java高階架構師設計-JavaEE拓展 03-ja

LeetCode每天一】Combination Sum II組合和II

turn mic and microsoft str find get break .so Given a collection of candidate numbers (candidates) and a target number (target), find all

重構改善既有代碼設計--重構手法01Extract Method 提煉函

設置 都是 覆寫 list() 為什麽 新建 細粒度 align 容易 背景: 你有一段代碼可以被組織在一起並獨立出來。將這段代碼放進一個獨立函數,並讓函數名稱解釋該函數的用途。 void PrintOwing(double amount)

R語言隨機抽樣sample函

.cn png 函數 -1 數據集 img image 如果 一個數 如果想從一堆數據集中隨機抽出一個數,用sample函數就能實現,代碼展示如下: forehead<-c(249,189,128,111,184,233,313,120,151,196,135,

MATLAB學習筆記符號計算積分+導

2.3 .1符號微積分  求極限   limit(f,x,a) 求f(x)中x趨近於a的極限值 例如: >> clear >> syms k x >> lim_t=limit((1-1/x)^(k*x),x,inf) lim_t =

LeetCode23合併K個有序連結串列JAVA實現

題目: 我的解答: 思路很簡單,把所有的資料先讀到ArrayList中然後轉到陣列中,然後排序,然後構建新連結串列 程式碼: /** * Definition for singly-linked list. * public class ListNode {

LeetCode24兩兩交換連結串列的節點JAVA實現

題目: 我的解答: /** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(i

LeetCode18之和JAVA實現

題目: 我的解答: public List<List<Integer>> fourSum(int[] nums, int target) { Arrays.sort(nums); List<List<Integer>&

leetcode32最長有效括號遇到一個奇葩的錯誤

問題描述: 給一個只包含 '(' 和 ')' 的字串,找出最長的有效(正確關閉)括號子串的長度。 對於 "(()",最長有效括號子串為 "()" ,它的長度是 2。 另一個例子 ")()())",最長有效括號子

leetcode72編輯距離

給定兩個單詞 word1 和 word2,計算出將 word1 轉換成 word2 所使用的最少運算元 。 你可以對一個單詞進行如下三種操作: 插入一個字元 刪除一個字元 替換一個字元 示例 1:

leetcode兩個有序陣列的中位數

給定兩個大小為 m 和 n 的有序陣列 nums1 和 nums2。 請你找出這兩個有序陣列的中位數,並且要求演算法的時間複雜度為 O(log(m + n))。 你可以假設 nums1 和 nums2 不會同時為空。 示例

leetcode11盛水最多的容器

給定 n 個非負整數 a1,a2,...,an,每個數代表座標中的一個點 (i, ai) 。在座標內畫 n 條垂直線,垂直線 i 的兩個端點分別為 (i, ai) 和 (i, 0)。找出其中的兩條線,

leetcode26刪除排序陣列的重複項

給定一個排序陣列,你需要在原地刪除重複出現的元素,使得每個元素只出現一次,返回移除後陣列的新長度。 不要使用額外的陣列空間,你必須在原地修改輸入陣列並在使用 O(1) 額外空間的條件下完成。 給定陣列 nums = [1,1,2], 函式應該返回新的長度 2, 並且原陣列 nums 的前兩個元素被修改