動態規劃比遞迴快-LeetCode91-解碼方法
阿新 • • 發佈:2018-12-04
題目
一條包含字母 A-Z 的訊息通過以下方式進行了編碼:
'A' -> 1
'B' -> 2
...
'Z' -> 26
給定一個只包含數字的非空字串,請計算解碼方法的總數。
示例 1:
輸入: "12"
輸出: 2
解釋: 它可以解碼為 "AB"(1 2)或者 "L"(12)。
示例 2:
輸入: "226"
輸出: 3
解釋: 它可以解碼為 "BZ" (2 26), "VF" (22 6), 或者 "BBF" (2 2 6) 。
思路1
遞迴。分為兩種情況:選前一個數解碼和選前兩個數解碼。然後將這兩種情況解碼數加起來。超時。
程式碼1
class Solution { public int numDecodings(String s) { if(s.charAt(0)=='0'){ return 0; } if(s.length()==1){ return 1; } // 1個 int singlenum=0; singlenum=numDecodings(s.substring(1)); // 2個 int doublenum=0; if(Integer.parseInt(s.substring(0,2))>26){ }else{ if(s.length()==2){ doublenum=1; }else{ doublenum=numDecodings(s.substring(2)); } } return singlenum+doublenum; } }
思路2
遍歷s。List<Integer>記錄目前所有解碼方式的最後數字。List.size即為所求。
如果當前字元不為'0' :遍歷List<Integer>拿到所有解碼方式的最後數字與當前字元結合為兩位數(或三位數),如果<=26則新增解碼方式。並將原解碼方式最後數字更新為當前字元。
如果當前字元為'0' :遍歷List<Integer>拿到所有解碼方式的最後數字與當前字元結合為兩位數(或三位數),如果<=26則新增解碼方式。並刪除錯誤的解碼方式(因為0不能單獨作為解碼)。
超時。
程式碼2
class Solution { public int numDecodings(String s) { if(s.charAt(0)=='0'){ return 0; } List<Integer> l=new ArrayList<Integer>(); l.add(s.charAt(0)-'0'); for(int i=1;i<s.length();i++){ if(s.charAt(i)!='0'){ int lsize=l.size(); for(int j=0;j<lsize;j++){ if( l.get(j)*10 + s.charAt(i)-'0'<= 26){ l.add(l.get(j)*10 + s.charAt(i)-'0'); } l.set(j,s.charAt(i)-'0'); } }else{ int lsize=l.size(); for(int j=0;j<lsize;j++){ if( l.get(j)*10 + s.charAt(i)-'0'<= 26){ l.add(l.get(j)*10 + s.charAt(i)-'0'); } l.set(j,s.charAt(i)-'0'); } for(int j=0;j<l.size();j++){ if(l.get(j)==0){ l.remove(j); j--; } } } } return l.size(); } }
思路3
動態規劃。int[] res記錄當前字串解碼數量。res[res.length-1]即為所求。
初始化res[0]=1。
尋找規律可以發現:
1.當前字元為 '0' : res[i]=res[i-2]
2.前一個字元為'0' : res[i]=res[i-1]
3.當前字元非0: 當前字元與前一個字元組合成兩位數。若<=26,則res[i]=res[i-1]+res[i-2];否則res[i]=res[i-1]。
程式碼3
class Solution { public int numDecodings(String s) { if(s.charAt(0)=='0'){ return 0; } int[] res=new int[s.length()]; res[0]=1; for(int i=1;i<s.length();i++){ // 無法解碼的情況 if(s.charAt(i)=='0' && s.charAt(i-1)=='0'){ return 0; } if(s.charAt(i)=='0' && (s.charAt(i-1)-'0')*10+s.charAt(i)-'0' > 26){ return 0; } // 0的情況 if(s.charAt(i)=='0'){ if(i-2>=0){ res[i]=res[i-2]; }else{ res[i]=res[i-1]; } continue; } // 前一個是0的情況 if(s.charAt(i-1)=='0'){ res[i]=res[i-1]; continue; } // 非0情況 if( (s.charAt(i-1)-'0')*10+s.charAt(i)-'0' <= 26){ if(i-2>=0){ res[i]=res[i-1]+res[i-2]; }else{ res[i]=res[i-1]*2; } }else{ res[i]=res[i-1]; } } return res[s.length()-1]; } }
總結
動態規劃比遞迴快。