Leetcode - Decode Ways

My code:

public class Solution {
    public int numDecodings(String s) {
        if (s == null || s.length() == 0)
            return 0;
        if (s.charAt(0) < '1' || s.charAt(0) > '9')
            return 0;
        else if (s.length() == 1)
            return 1;
        int[] dp = new int[s.length() + 1];
        if (s.charAt(0) >= '1' && s.charAt(0) <= '9')
            dp[1] = 1;
        else
            dp[1] = 0;
        dp[0] = 1;
        for (int i = 2; i < dp.length; i++) {
            if (s.charAt(i - 1) < '0' || s.charAt(i - 1) > '9')
                return 0;
            int v = Integer.parseInt(s.substring(i - 2, i));
            
            if (v > 9 && v <= 26)
                dp[i] += dp[i - 2];
            if (s.charAt(i - 1) > '0' && s.charAt(i - 1) <= '9')
                dp[i] += dp[i - 1];
            else if (s.charAt(i - 1) == '0' && dp[i] == 0)
                return 0;
        }
        return dp[dp.length - 1];
    }
    public static void main(String[] args) {
        Solution test = new Solution();
        System.out.println(test.numDecodings("10"));
    }
}

My test result:

Paste_Image.png

這道DP花了我接近兩個小時拼弃,看了別人的代碼主慰,理解了好久才搞懂递惋。
其實访惜,DP的話,思路一定要清晰宙址。比如這道題目轴脐。
求這個東西。
那么我設一個數組抡砂, dp[s.length()+1]
dp[i] 表示從s[0] - s[i - 1] 這一段區(qū)域大咱,有多少種構造方法。
那么舀患,有多少種呢徽级?只有兩種可能。

  1. (s[i - 2], s[i - 1])
  2. (s[i - 2]), (s[i - 1])
    那么就直接點聊浅,考慮第一種因素餐抢。
    即前面兩位在 1-26之間就行了。
    于是低匙,dp[i] += dp[i - 2], 先把第一種情況加上去
    這個很容易計算旷痕。
    此時,不需要去考慮什么0不0的顽冶。
    然后考慮第二種情況欺抗。
    那么,因為DP强重,我可以保證s[i - 2] 是符合的绞呈。
    于是只用判斷s[i - 1]是否符合 1-9.
    如果是贸人, dp[i] += dp[i - 1]
    然后還需要考慮一種情況, 如果 s[i - 1] == '0' 呢佃声?
    按道理艺智,是無法進行下去了,應該直接返回0.
    但是如果s[i - 2] 在 1-2范圍內圾亏,就可以構成十拣,10, 20,于是可以繼續(xù)進行下去志鹃。
    那么該怎么區(qū)分這種情況呢夭问?難道還要再去判斷下s[i - 2]?
    不用了曹铃,如果s[i - 2] 在 1-2 范圍內缰趋,就滿足了第一種情況,那么dp[i] 就已經被賦值了陕见,已經大于0了埠胖。
    所以最后只用判斷下dp[i]是否為0,是否被賦值過了淳玩,如果沒有。代表s[i - 2]不在1-2范圍內非竿。那么這里就無法再繼續(xù)decode蜕着,得直接返回0.

一開始這道題目我是拿遞歸做的,思路和permutation那個類型差不多红柱,但是超時了承匣。的確其中有許多重復的地方。

DP還是難啊锤悄。
貼一個博客韧骗。
http://bangbingsyb.blogspot.com/2014/11/leetcode-decode-ways.html

DP,思路一定要清晰零聚,最好能像這里一樣清楚地寫下來袍暴。

**
總結: String, DP
**

Good luck, Richardo!

My code:

public class Solution {
    public int numDecodings(String s) {
        if (s == null || s.length() == 0) {
            return 0;
        }

        int n = s.length();
        int[] dp = new int[n];
        dp[0] = (isDigit(s.charAt(0)) ? 1 : 0);
        for (int i = 1; i < n; i++) {
            int sum = 0;
            char curr = s.charAt(i);
            if (isDigit(curr)) {
                if (i - 1 >= 0) {
                    sum += dp[i - 1];
                }
                else {
                    sum += 1;
                }
            }
            String sub = s.substring(i - 1, i + 1);
            if (isValid(sub)) {
                if (i - 2 >= 0) {
                    sum += dp[i - 2];
                }
                else {
                    sum += 1;
                }
            }
            dp[i] = sum;
        }
        
        return dp[n - 1];
    }
    
    private boolean isValid(String s) {
        char c1 = s.charAt(0);
        char c2 = s.charAt(1);
        if (c1 == '1' && (c2 >= '0' && c2 <= '9')) {
            return true;
        }
        else if (c1 == '2' && (c2 >= '0' && c2 <= '6')) {
            return true;
        }
        else {
            return false;
        }
    }
   
    private boolean isDigit(char curr) {
        if (curr >= '1' && curr <= '9') {
            return true;
        }
        else {
            return false;
        }
    }
}

這道題目我的思路還是很清晰的。
一開始我做的方向不對隶症。
我又想到了用 divide and conquer, burst ballon + cache
這是一定可以work的政模。但存在一個問題,很難解決蚂会,或者需要很多的瑣碎代碼去解決淋样。
如果輸入是 '111'
那么,我的算法胁住,會重復計算很多東西趁猴。而且很難察覺刊咳。只能通過hashset 來去重。這樣的話儡司,開銷會變大娱挨。

于是我轉而用 iteration DP.

dp[i] 表示, [0, i] number of decode ways
那么枫慷,
如果 s.charAt(i) 本身就是digit让蕾,dp[i] += dp[i - 1]
如果 s.substring(i - 1, i + 1) 是 "11 - 26"中的一員,那么
dp[i] += dp[i - 2]

然后加上一些corner case, 就可以完成這個問題了或听。
思路很直接探孝。

Anyway, Good luck, Richardo! -- 08/26/2016

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市誉裆,隨后出現的幾起案子顿颅,更是在濱河造成了極大的恐慌,老刑警劉巖足丢,帶你破解...
    沈念sama閱讀 217,657評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件粱腻,死亡現場離奇詭異,居然都是意外死亡斩跌,警方通過查閱死者的電腦和手機绍些,發(fā)現死者居然都...
    沈念sama閱讀 92,889評論 3 394
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來耀鸦,“玉大人柬批,你說我怎么就攤上這事⌒涠” “怎么了氮帐?”我有些...
    開封第一講書人閱讀 164,057評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長洛姑。 經常有香客問我上沐,道長,這世上最難降的妖魔是什么楞艾? 我笑而不...
    開封第一講書人閱讀 58,509評論 1 293
  • 正文 為了忘掉前任参咙,我火速辦了婚禮,結果婚禮上产徊,老公的妹妹穿的比我還像新娘昂勒。我一直安慰自己,他們只是感情好舟铜,可當我...
    茶點故事閱讀 67,562評論 6 392
  • 文/花漫 我一把揭開白布戈盈。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪塘娶。 梳的紋絲不亂的頭發(fā)上归斤,一...
    開封第一講書人閱讀 51,443評論 1 302
  • 那天,我揣著相機與錄音刁岸,去河邊找鬼脏里。 笑死,一個胖子當著我的面吹牛虹曙,可吹牛的內容都是我干的迫横。 我是一名探鬼主播,決...
    沈念sama閱讀 40,251評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼酝碳,長吁一口氣:“原來是場噩夢啊……” “哼矾踱!你這毒婦竟也來了?” 一聲冷哼從身側響起疏哗,我...
    開封第一講書人閱讀 39,129評論 0 276
  • 序言:老撾萬榮一對情侶失蹤呛讲,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后返奉,有當地人在樹林里發(fā)現了一具尸體贝搁,經...
    沈念sama閱讀 45,561評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,779評論 3 335
  • 正文 我和宋清朗相戀三年芽偏,在試婚紗的時候發(fā)現自己被綠了雷逆。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,902評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡污尉,死狀恐怖关面,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情十厢,我是刑警寧澤,帶...
    沈念sama閱讀 35,621評論 5 345
  • 正文 年R本政府宣布捂齐,位于F島的核電站蛮放,受9級特大地震影響,放射性物質發(fā)生泄漏奠宜。R本人自食惡果不足惜包颁,卻給世界環(huán)境...
    茶點故事閱讀 41,220評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望压真。 院中可真熱鬧娩嚼,春花似錦、人聲如沸滴肿。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至贵少,卻和暖如春呵俏,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背滔灶。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評論 1 269
  • 我被黑心中介騙來泰國打工普碎, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人录平。 一個月前我還...
    沈念sama閱讀 48,025評論 2 370
  • 正文 我出身青樓麻车,卻偏偏與公主長得像,于是被迫代替她去往敵國和親斗这。 傳聞我的和親對象是個殘疾皇子动猬,可洞房花燭夜當晚...
    茶點故事閱讀 44,843評論 2 354

推薦閱讀更多精彩內容