Chinaunix首页 | 论坛 | 博客
  • 博客访问: 120652
  • 博文数量: 53
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 620
  • 用 户 组: 普通用户
  • 注册时间: 2014-08-24 16:22
文章存档

2014年(53)

我的朋友

分类: C/C++

2014-09-06 13:50:01

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

这道题是很好的一道关于动态规划的题。
对于动态规划,基本思路是考察f[n]和f[n-1]的关系,也就是教科书上说的“最优子结构”,如果得到从f[n-1]推导出的f[n]的公式,编程就变成了很简单的事。
这道题我的第一感觉是卡特兰数,从输入字符串的第k个字符把它一分为二,计算f(n+1)=西格玛f(k)*f(n-k),但是后来想想,f(i)和f(n-i)不是相乘关系,因为相乘会导致大量重复的结果。
然后想到这么一个思路:假设输入字符串为xxxxxxxxxxxxxxmn,也就是说,最后两位是m和n,那么mn两个字符一起解码的解和n单独解码的解完全的组成了题目的解空间(mn被拆开解码和mn没有被拆卡解码两种情况),假如f(string s) 表示s的解码方式个数,那么:
f("xxxxxxxxxxxxxxmn")=f("xxxxxxxxxxxxxxm")+f("xxxxxxxxxxxxxx")
用动态规划做的话,需要申请一个数组num[s.length()+1],那么
num[i]=num[i-1]+num[i-2],2<=i<=s.length()
写的时候需要考虑各种非法情况,code如下:

  1. int numDecodings(string s) {
  2.         vector<int> num(s.length()+1);
  3.         if(s.length()==0)
  4.             return 0;
  5.         num[0]=1;
  6.         if(s[0]=='0')
  7.             num[1]=0;
  8.         else
  9.             num[1]=1;
  10.         for(int i=2;i<=s.length();i++){
  11.             if('1'==s[i-2] && '1'<=s[i-1] && s[i-1]<='9')
  12.                 num[i]=num[i-1]+num[i-2];
  13.             else if('2'==s[i-2] && '1'<=s[i-1] && s[i-1]<='6')
  14.                 num[i]=num[i-1]+num[i-2];
  15.             else if('1'<=s[i-2] && s[i-2]<='2' && s[i-1]=='0')
  16.                 num[i]=num[i-2];
  17.             else if(('0'==s[i-2] || '2'<s[i-2]) && '0'==s[i-1])
  18.                 num[i]=0;
  19.             else
  20.                 num[i]=num[i-1];
  21.         }
  22.         return num[s.length()];
  23.     }


阅读(911) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~