有一种将字母编码成数字的方式:'a'->1, 'b->2', ... , 'z->26'。
现在给一串数字,给出有多少种可能的译码结果。
def fibonacci(n): ##计算连续n个两两都小于27的数字可以有多少种编码方式,比如 1212 一共有5种
if n < 3:
return n
return fibonacci(n-1) + fibonacci(n-2)
def sol(a):
if a == "0":
return 0
if "00" in a:
return 0 ## 连续两个0,则一定无法编码
str_1 = "" ## 保存那些位上的数字可以和之后的组成小于27的数字
for i in range(len(a)-1):
if int(a[i:i+2])<=26 and int(a[i])>0 and int(a[i+1])!=0:
str_1 += "1"
else:
str_1 += "0"
s = 1
l1 = str_1.strip().split("0")
for x in l1:
s *= fibonacci(len(x)+1)
return s
print(sol(a)) import java.util.Scanner;
public class Main {
public static int process(char[] ch, int i) {
if (i == ch.length) {
return 1;
}
if (ch[i] == '0') {
return 0;
}
if (ch[i] == '1') {
int res = process(ch, i + 1);
if (i + 1 < ch.length) {
res += process(ch, i + 2);
}
return res;
}
if (ch[i] == '2') {
int res = process(ch, i + 1);
if (i + 1 < ch.length && ch[i] >= '0' && ch[i + 1] <= '6') {
res += process(ch, i + 2);
}
return res;
}
return process(ch, i + 1);
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String str = sc.next();
if (str.length() < 1) {
System.out.println(0);
} else {
System.out.println(process(str.toCharArray(), 0));
}
}
}
function f(str) {str = str.toString() // 参数转成字符串let arr = str.split('')if (arr.length === 1) // 参数只有一位,那么返回的种类就一种return 1}if (arr.length === 2) { // 参数字符串两位位,那种类就取决于这个两位数的大小if (parseInt(arr[0] + arr[1]) <= 26) {return 2 // 小于等于26就能转化为一个字母,那么就有两种字母对应方式} else {return 1 // 大于26就能转化为一个字母,那么只有一种字母对应方式}}let arr1 = arr.concat() // 防止数组的引用传递,这里拷贝一份arr1.pop() // 去掉后一位let str1 = arr1.join('')let arr2 = arr.concat()if (parseInt(arr2.slice(-2).join('')) > 26) { // 判断被去掉的两位数是否大于26return f(str1) // 递归,种类数仅有f(str切掉后一位)} else {arr2.pop()arr2.pop()let str2 = arr2.join('')return f(str1) + f(str2)// 递归,种类数有f(str切掉后一位) + f(str切掉后2位)种}}
# -*- coding:utf-8 -*- #python解法''' dp(n):n个字符可能的结果 1.s[i-2]和s[i-1] 两个字符是10----26之间但不包括10和20这两个数时: eg:判断“567123”的编码方式可以转为判断“56712”+‘3“或者”5671“+”23“的问题。即dp(n)=dp(n-1)+dp(n-2)。 2.s[i-2]和s[i-1] 两个字符10或20这两个数时,只有一种编码方式,比如10------>[“J”], 所以dp[i] = dp[i-2] 3.s[i-2]和s[i-1] 两个字符不在上述两种范围时,比如27,所以dp[i] = dp[i-1] 4.数字”0“对应的编码只能是和其前一个数字组合对应的编码,如果和其前一个字符组合后不存在对应编码,则编码方式为0. ''' dp = [1,1] s = raw_input().strip() if s=='' or s[0]=='0': dp = [0,0] #此时下面的for不会运行,也不报错 for i in range(2, len(s) + 1): if 10 <= int(s[i - 2:i]) <= 26 and s[i - 1] != '0': # 1 dp.append(dp[i - 1] + dp[i - 2]) elif int(s[i - 2:i]) == 10 or int(s[i - 2:i]) == 20: # 2 dp.append(dp[i - 2]) elif s[i - 1] != '0': # 3 dp.append(dp[i - 1]) else: dp.append(0) # 4 print dp[len(s)]
#include<bits/stdc++.h>
using namespace std;
int numDecodings(string s) {
if(!s.size() || s.front() == '0') return 0;
int r1 = 1, r2 = 1;
for (int i = 1; i < s.size(); i++){
if (s[i] == '0') r1 = 0;
if (s[i-1] == '1' || s[i-1] == '2' && s[i] <= '6'){
r1 = r2+r1;
r2 = r1-r2;
}
else
r2 = r1;
}
return r1;
}
int main(){
string s;
while(cin >> s){
cout << numDecodings(s) << endl;
}
return 0;
}
LeetCode #91。
C++ 动态规划方法
主要有四种情况
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int numOfDecodings(string s) {
int len = s.size();
if (!len || s[0] == '0') return 0;
vector<int> nums(len, 0);
nums[0] = 1;
if (s[1] == '0' && s[0] <= '2') nums[1] = 1;
else if (s[0] == '1' || (s[0] == '2' && s[1] <= '6')) nums[1] = 2;
else if (s[1] == 0) nums[1] = 0;
else nums[1] = 1;
for (int i = 2; i < len; ++i) {
if (s[i] == '0' && s[i - 1] <= '2' && s[i - 1] > '0') nums[i] = nums[i - 2];
else if (s[i - 1] == '1' || (s[i - 1] == '2' && s[i] <= '6')) nums[i] = nums[i - 1] + nums[i - 2];
else if (s[i] == '0') nums[i] = 0;
else nums[i] = nums[i - 1];
}
return nums[len - 1];
}
int main(void) {
string in;
int num = 0, len = in.length();
cin >> in;
cout << numOfDecodings(in) << endl;
return 0;
}
if __name__ == "__main__": s = str(input()) if s == '' or s[0] == '0': print(0) exit() dp = [1] for i in range(1, len(s) + 1): dp.append((0 if (s[i - 1] == '0') else dp[i - 1])) if(i > 1 and (s[i - 2] == '1' or (s[i - 2] == '2' and s[i - 1] <= '6'))): dp[i] += dp[i - 2] print(dp[len(s)])
class MainActivity: def main(self): # Read the data s = input() if '00' in s: print(0) return # Initialization results = [1, 0 if s[0] == '0' else 1] # Traverse for ptr in range(1, len(s)): part = int(s[ptr - 1: ptr + 1]) if part <= 10&nbs***bsp;part == 20&nbs***bsp;part > 26: results.append(results[-1]) else: results.append(sum(results)) results.pop(0) print(results[-1]) if __name__ == '__main__': M = MainActivity() M.main()
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
String s = in.nextLine();
back(s, 0);
System.out.println(cnt);
}
// 数字转字母的编码需要考虑0-回溯爆搜
static int cnt = 0;
public static void back(String s, int idx) {
if (idx == s.length()) {
cnt++;
return;
}
// 选一个
int i = s.charAt(idx) - '0';
if (i > 0 && i <= 9) {
back(s, idx + 1);
}
// 选两个
if (idx+1 <= s.length()-1) {
int j = s.charAt(idx+1) - '0';
int sum = i * 10 + j;
if (sum >= 10 && sum <= 26) {
back(s, idx + 2);
}
}
}
}
#include <bits/stdc++.h>
using namespace std;
int numDecodings(string s) {
if (s[0] == '0') return 0;
vector<int> dp(s.size() + 1, 0); // dp[i]表示前i个字符可能的解码结果
dp[0] = 1; dp[1] = 1;
for (int i = 2; i <= s.size(); i++) {
if (s[i - 1] == '0') { // 字符下标从0开始,这里i从2开始,所以用i - 1索引当前字符下标
if (s[i - 2] == '1' || s[i - 2] == '2') { // 单独考虑10和20
dp[i] = dp[i - 2];
}else {
return 0;
}
}else {
int num = (s[i - 2] - '0') * 10 + s[i - 1] - '0';
if (num >= 10 && num <= 26) { // 因为当前字符不可能为0,所以在10和26之间的数不可能是10和20
dp[i] = dp[i - 1] + dp[i - 2];
}else {
dp[i] = dp[i - 1];
}
}
}
return dp[s.size()];
}
int main() {
string s;
cin >> s;
int result = numDecodings(s);
cout << result << endl;
return 0;
} #include <cstdio>
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main()
{
string str;
cin >> str;
int n = str.length();
int bZero = false;
if (str[0]=='0') bZero = true;
for (int i = 1; i < n; ++i)
{
if (str[i]=='0'&&str[i-1]=='0')
{
bZero = true;
break;
}
}
if (bZero)
{
printf("0\n");
return 0;
}
vector<int> dp(n+1, 0);
dp[0] = dp[1] = 1;
for (int i = 2; i <= n; ++i)
{
if (str[i-1]!='0') dp[i] = dp[i-1];
int x = (str[i-2]-'0')*10+(str[i-1]-'0');
if (x<=26 && x>=10)
dp[i] += dp[i-2];
}
printf("%d\n", dp[n]);
return 0;
} import sys line=sys.stdin.readline().strip() sum = [0 for i in range(len(line))] for i in range(len(line)): if(line[i] != '0'): x = 1 if(i==0) else sum[i-1] sum[i] += x if(i > 0 and line[i - 1] != '0' and eval(line[i-1]+line[i]) <= 26): x = 1 if(i==1) else sum[i-2] sum[i] += x print(sum[len(line)-1])
/*
借鉴楼上的动态规划的想法,把规则总结得简单些;
dp[n] 为 1~n 个字符的解码方式
0.若字符串为空,或第一个字符为 '0',直接输出0.
1.初始化:dp[0]=1; dp[1]=1; // 无字符的解码方式为1,前1个字符的解码方式为1
2.(a) 若当前字符不为 '0':dp[j] += dp[j-1];
(b) 若当前字符和前一个字符组成的数字 tmp,满足 10<=tmp<=26,dp[j] += dp[j-2];
(c) 不满足 (a)(b) 解码条件,无法解码,退出输出 0
*/
#include<bits/stdc++.h>
using namespace std;
int main(){
string s;
cin>> s;
if(s[0]=='0' || s.empty()){
cout<< 0 << endl;
}else{
int sl = s.size();
vector<int> dp(sl+1, 0);
dp[0] = 1;
dp[1] = 1;
for(int i=1; i<sl; ++i){
int j = i+1;
int tmp = (s[i-1]-'0')*10 + (s[i]-'0');
if(s[i]!='0'){
dp[j] += dp[j-1];
}
if(10<=tmp && tmp<=26){
dp[j] += dp[j-2];
}
if(dp[j]==0){
dp[sl] = 0;
break;
}
}
cout<< dp[sl] << endl;
}
return 0;
} import java.util.Scanner;
public class Main {
public static void main( String[] args ) {
Scanner sc = new Scanner( System.in );
while ( sc.hasNext() ) {
String str = sc.next();
if( str.charAt(0) == '0' ) System.out.println( 0 );
else {
int[] dp = new int[str.length()+1];
dp[0] = 1;
dp[1] = 1;
for( int i = 2; i <= str.length(); i ++ ) {
int tmp = 0;
if( str.charAt(i-1) != '0' ) tmp += dp[i-1];
int num = Integer.parseInt( str.substring(i-2,i) );
if( num > 9 && num < 27 ) tmp += dp[i-2];
if( tmp != 0 ) dp[i] = tmp;
else {
dp[str.length()] = 0;
break;
}
}
System.out.println( dp[str.length()] );
}
}
sc.close();
}
}
def numdecode(s): if len(s)==0 or s[0]=='0': return 0 if len(s)==1: return 1 num=[] for i in range(len(s)): num.append(1) if s[1]=='0' and s[0]<='2': num[1]=1 elif s[0]=='1' or (s[0]=='2' and s[1]<='6'): num[1]=2 elif s[1]=='0': num[1]=0 else: num[1]=1 for i in range(2,len(s)): if s[i]=='0' and s[i-1]<='2' and s[i-1]>'0': num[i]=num[i-2] elif s[i-1]=='1' or (s[i-1]=='2' and s[i]<='6'): num[i]=num[i-1]+num[i-2] elif s[i]=='0': num[i]=0 else: num[i]=num[i-1] return num[-1] while True: try: ss=input() res=numdecode(ss) print(res) except: break