LeetCode091 Decode Ways

详细见:leetcode.com/problems/decode-ways


Java Solution: github

package leetcode;

import java.util.ArrayList;


/*
 * 	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.
 */

public class P091_DecodeWays {
	public static void main(String[] args) {
//		System.out.println(new Solution().numDecodings("102020"));
//		System.out.println(new Solution().numDecodings("1120121"));
//		System.out.println(new Solution().numDecodings("1127121"));
		System.out.println(new Solution().numDecodings("10"));
	}
	/*
	 * 	算法题,很多都是仔细分析
	 * 	别慌,一慌什么都完了
	 * 	AC
	 * 	在慌的时候,WA好多次
	 * 	5 ms
	 */
	static class Solution {
		int[] arr = null;
		int count = 1;
		ArrayList<Integer> help = null;
		final int sign_init = -1, sign_0 = 0, sign_1 = 1, 
				sign_2 = 2, sign_3_7 = 37, sign_else = 3;
	    public int numDecodings(String s) {
	    	if (s == null || s.length() == 0) {
	    		return 0;
	    	} else if (s.equals("0")) {
	    		return 0;
	    	}
	    	arr = new int[s.length()];
	    	help = new ArrayList<Integer>();
	    	help.add(1);
	    	help.add(2);
	    	for (int i = 0; i != arr.length; i ++) {
	    		arr[i] = s.charAt(i) - '0';
	    	}
	    	int i = 0, pre_sign = sign_init;
	    	for (int j = 0; j != arr.length; j ++) {
	    		if (arr[j] < 0 || arr[j] > 26) {
	    			//出现非法输入
	    			if (i < j) {
	    				add(i, j - 1);
	    			} 
    				i = j + 1;
    				return 0;
	    		}
	    		//所有数字 [0 , 26]
	    		if (arr[j] == 0) {
	    			// 0的情况
	    			if (pre_sign == sign_1 || pre_sign == sign_2) {
	    				count *= add(i, j - 2);
	    				i = j + 1;
	    			} else {
	    				return 0;
	    			}
	    			if (j == arr.length - 1) {
	    				count *= add(i, j);
	    			}
	    			pre_sign = sign_0;
	    		} else if (arr[j] == 1) {
	    			// 1的情况
	    			if (j == arr.length - 1) {
	    				count *= add(i, j);
	    			}
	    			pre_sign = sign_1;
	    		} else if (arr[j] == 2) {
	    			// 需要注意后者是否[0 ~ 6]
	    			if (j == arr.length - 1) {
	    				count *= add(i, j);
	    			}
	    				
	    			pre_sign = sign_2;
	    		} else if (arr[j] < 7) {
	    			// 3 4 5 6
	    			// 只是需要注意前面是否是2
	    			if (pre_sign == sign_1 || pre_sign == sign_2) {
	    				count *= add(i, j);
	    				i = j + 1;
	    			} else { 
	    				// 包含
	    				// pre_sign == sign_init
	    				// pre_sign == sign_0
	    				// pre_sign == sign_3_7
	    				// pre_sign == sign_else
	    				i = j + 1;
	    			}
	    			pre_sign = sign_3_7;
	    		} else {
	    			// 7 8 9
	    			// 对arr[j] < 7的情况,只是不需要考虑2的情况
	    			if (pre_sign == sign_1) {
	    				count *= add(i, j);
	    				i = j + 1;
	    			} else if (pre_sign == sign_2) { 
	    				count *= add(i, j - 1);
	    				i = j + 1;
	    			} else {
	    				// 包含
	    				// pre_sign == sign_init
	    				// pre_sign == sign_0
	    				// pre_sign == sign_3_7
	    				// pre_sign == sign_else
	    				i = j + 1;
	    			}
	    			pre_sign = sign_else;
	    		}
	    	}
	        return count;
	    }
		private int add(int i, int j) {
			if (i > j || i < 0 || j < 0) {
				return 1;
			} else if (j - i < help.size()) {
				return help.get(j - i);
			} else {
				int k = help.size();
				int k1 = k - 1;
				int k2 = k - 2;
				for (; k <= j - i; k ++) {
					help.add(help.get(k1 ++) + help.get(k2 ++));
				}
				return help.get(j - i);
			}
		}
	}
}


C Solution: github

/*
    url: leetcode.com/problems/decode-ways
    AC 3ms 22.50%
*/

#include <stdio.h>
#include <stdlib.h>

int numDecodings(char* s) {
    char c;
    int i = 0;
    int cnt = 0, p1 = 0, p2 = 0;
    int v = 0;
    while (1) {
        c = s[i];
        p2 = p1;
        p1 = cnt;
        if (c == '\0') break;
        if (i == 0) {
            if (c == '0') return 0;
            cnt = 1;
        } else {
            v = (s[i-1]-'0') * 10 + s[i] - '0';
            if (i == 1) {
                if (v % 10 == 0) {
                    if (v > 20 || v == 0) return 0;
                } else {
                    if (v > 10 && v < 27) cnt = 2;
                    if (v > 0 && v < 10) cnt = p1;
                }
            } else {
                if (v % 10 == 0) {
                    if (v > 20 || v == 0) return 0;
                    cnt = p2;
                } else {
                    if (v > 10 && v < 27) cnt += p2;
                    if (v > 0 && v < 10) cnt = p1;
                }
            }
        }
        i ++;
    }
    return cnt;
}

int main() {
    char* s = "10298212029821202120821272721202812928221721202821278171";
    printf("answer is %d\r\n", numDecodings(s));
    return 0;
}


Python Solution: github

#coding=utf-8

'''
    url: leetcode.com/problems/decode-ways
    @author:     zxwtry
    @email:      zxwtry@qq.com
    @date:       2017年4月23日
    @details:    Solution: 52ms 60.05%
'''

class Solution(object):
    def numDecodings(self, s):
        """
        :type s: str
        :rtype: int
        """
        sn = 0 if s == None else len(s)
        if sn == 0 or s[0] == '0': return 0
        v1, a1, a2 = int(s[0]), 1, 1
        for i in range(1, sn):
            v0 = int(s[i])
            if v0 == 0:
                if v1 in {1, 2}:
                    a2, a1=a1, a2
                else: return 0
            elif v1 == 1 or (v1==2 and v0<7):
                a2, a1 = a1, a1+a2
            else: a2, a1 = a1, a1
            v1 = v0
        return a1
    

if __name__ == "__main__":
    m = [
            '0',
            '1',
            '9',
            '10',
            '11',
            '19',
            '20',
            '21',
            '29',
            '30',
            '88',
        ]
    for s in m:
        print("%s \t %d" % (s, Solution().numDecodings(s)))


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值