LeetCode 90. Decode Ways

动态规划,dp[i]代表字符串s.substr(0, i) decode ways的数量.

注意到0只能在10,20中出现,亦即字符串包含0时,前面的数字只能为1或2.


1) 当s[i]为0时 

若s[i-1]不为1或2, 直接返回0;

若s[i-1]为1或1, dp[i] = dp[i-1]

2) 当s[i]不为0时

若s[i-1]为0, dp[i] = dp[i-1].

若i+1<s.size(), s[i+1]为0, dp[i] = dp[i-1]. (语义是当前这个数只能后面的0组成一个数,而这个数是否合法(为10或20), 则交由考察s[i+1]时判定)

若string_to_int(s.substr(i-1, 2))<=26, dp[i] = dp[i-1] + dp[i-2] (此时可将s[i-1]和s[i-2]看成一个字符,那么有dp[i-2]种可能;或仍当做单独的两个字符,那么有dp[i-1]种可能)

其他情况,dp[i] = dp[i-1].


代码:

class Solution 
{
public:
    int numDecodings(string s) 
    {
    	if ( s.empty() )
    	{
    		return 0;
    	} else if ( s[0] == '0' )
    	{
    		return 0;
    	} else if ( s.size() == 1)
    	{
    		return 1;
    	}

    	vector<int> dp(s.size(), 1);
    	if (s[1] == '0')
    	{
    		if (s[0]!='1' && s[0]!='2')
    		{
    			return 0;
    		} else
    		{
    			dp[1] = dp[0];
    		}
    	} else 
    	{
    		if (2<s.size() && s[2]=='0')
    		{
    			dp[1] = dp[0];
    		} else
    		{
				dp[1] = dp[0] + (string_to_int(s.substr(0, 2))<=26? 1: 0);    			
    		}
    	}
    	for (size_t i = 2; i < s.size(); ++ i)
    	{
    		if (s[i]=='0')
    		{
    			if (s[i-1]!='1' && s[i-1]!='2')
    			{
    				return 0;
    			} else
    			{
	    			dp[i] = dp[i-1];
	    		}
    		} else // 自身非0
    		{
    			if (s[i-1] == '0')
    			{
    				dp[i] = dp[i-1];
    			} else if (i+1<s.size() && s[i+1]=='0')
    			{
    				dp[i] = dp[i-1];
    			} else
	    		{
					dp[i] = dp[i-1] + (string_to_int(s.substr(i-1, 2))<=26? dp[i-2]: 0);    			
	    		}
	    	}
    	}

    	return dp.back();
    }
private:
	int string_to_int(const string& s)
	{
		int ret;
		stringstream ss;
		ss << s;
		ss >> ret;
		return ret;
	}
};


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值