给定一个字符串str,str全部由数字字符组成,如果str中的某一个或者相邻两个字符组成的子串值在1~26之间,则这个子串可以转换为一个字母。规定‘1’转换为“A”,“2”转换为“B”......"26"转化为“Z“。请求出str有多少种不同的转换结果,由于答案可能会比较大,所以请输出对取模后的答案。
输出一行仅有’0‘~’9‘组成的字符串,代表str 。
输出一个整数,代表你所求出的取模后答案。
1111
5
能转换出来的结果有:“AAAAA”,“LAA”,“ALA”,“AAL”,“LL”。
01
0
“0”没有对应的字符,而“01”是不可转换的。
18
2
时间复杂度,空间复杂度
import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.IOException; public class Main { public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); char[] str = br.readLine().toCharArray(); if(str.length == 0 || (str.length == 1 && str[0] == '0')) { System.out.println(0); // 一个0转化不成字母 }else if(str.length == 1){ System.out.println(1); // 一个非零数字只能有一种转化 }else{ int[] dp = new int[str.length + 1]; dp[0] = 1; // 没有字符,初始化为1 for(int i = 0; i < str.length; i++){ dp[i + 1] = str[i] == '0'? 0: dp[i]; // 如果前一个字符是1,或者前一个字符是2且当前字符是0~6,就可以和前一个字符组成两位数的字母转化 if(i > 0 && (str[i - 1] == '1' || str[i - 1] == '2' && str[i] <= '6')) { dp[i + 1] += dp[i - 1]; dp[i + 1] %= 1000000007; } } System.out.println(dp[dp.length - 1]); } } }
动态规划
(1) 第 i 个字符单独转换为 字母(和第一种情况一样) (2) 结合第 i-1 个字符,组合转换为 字母,如果是这种情况,那么,需要找出第 i-1 个字符单独转换为 字母 的方案数。因此,这种情况下,方案数 与 第 i-1 个字符单独转换为字母的方案数相同。
递推式
// 第 i 个字符只能单独转换为一个 字母 // dp[i-1] :第 i 个字符单独转换的方案数 dp[i]=dp[i-1]; // 第 i 个字符 可以和 第 i-1 个字符 共同转换为一个 字母 // dp[i-1] :第 i 个字符单独转换的方案数 // dp[i-2] :第 i 个字符,结合第 i-1 个字符组合转换为一个字母的方案数 dp[i]=dp[i-1]+dp[i-2];
题解
public class Main { private static String num; public static void main(String[] args) { Scanner in = new Scanner(System.in); num = in.next(); num = "0" + num; System.out.println(findLetter()); } private static int findLetter() { int[] dp = new int[num.length() + 1]; // 初始化 1:表示第 1 个字符只能有 1 种转换情况 dp[0] = 1; for (int i = 1; i < num.length(); ++i) { // 判断第 i 个字符能够转换为 字母的情况 // 0 不能转换 // 1 第 i 个字符只能单独转换为一个字母 // 2 第 i 个字符能够结合第 i-1 个字符转换为 一个字母 int judge = judge(i); if (judge == 0) { return 0; } if (judge == 1) { // dudge=1 dp[i] = dp[i - 1]; } else { // judge=2 dp[i] = (dp[i - 1] + dp[i - 2]) % 1000000007; } } return dp[num.length() - 1]; } // 判断第 i 个字符能够转换为 字母的情况 private static int judge(int i) { int count = 0; if (num.charAt(i) >= '1' && num.charAt(i) <= '9') { // 能够单独转换 count++; } if (num.charAt(i - 1) != '0') { int letter = Integer.valueOf(num.substring(i - 1, i + 1)); if (letter >= 10 && letter <= 26) { // 能够结合第 i-1 个字符一起转换 count++; } } return count; } }
import java.util.Scanner; public class Main{ public static void main(String[] args){ final long A = 1000000007; Scanner input = new Scanner(System.in); String inputString = input.nextLine(); // 如果长度为0或者首字符为0,直接返回 if (inputString.length() == 0 || inputString.charAt(0) == '0') { System.out.println(0); return; } int length = inputString.length(); long fn = 1; long fn_1 = 1; long fn_2 = 1; // 初始值要设对,可以通过长度为2的字符串来验证 for (int i = 1; i < length; ++i){ fn_2 = fn_1; fn_1 = fn; fn = 0; if (inputString.charAt(i) != '0'){ // i这一位单独可以转换 fn += fn_1; } int c = (inputString.charAt(i - 1) - '0') * 10 + (inputString.charAt(i) - '0'); if (c >= 10 && c <= 26){ // i和i-1可以组合转换 fn += fn_2; } if (fn == 0) { // 如果某个fn为0,那么结果一定为0 break; } fn %= A; } System.out.println(fn); } }
#include <bits/stdc++.h> using namespace std; const int M = 1000000007; int main(){ string s; cin>>s; int l = s.length(), p=1; int cnt = (s[l-1]=='0'?0:1); for(int i=l-2;i>=0;i--){ if(s[i]=='0'){ p = cnt; cnt = 0; }else{ int t = cnt; if((10*(s[i]-'0')+s[i+1]-'0')<=26) cnt = (cnt+p)%M; p = t; } } cout<<cnt<<endl; return 0; }
#include<bits/stdc++.h> using namespace std; int main() { string s; cin>>s; int cur = s[s.size() - 1] == '0' ? 0 : 1; int next = 1, tmp = 0; for (int i = s.size() - 2; i >= 0; i--){ if (s[i] == '0'){ next = cur; cur = 0; } else{ tmp = cur; if ((s[i] - '0') * 10 + s[i + 1] - '0' < 27) cur = (cur+next)%1000000007; next = tmp; } } cout<< cur%1000000007; return 0; }
import java.util.*; public class Main { public static int mod = (int)1e9 + 7; public static void main (String[] args) { Scanner sc = new Scanner(System.in); String s = sc.nextLine(); System.out.println(dpComboNum(s)); } /* public static long getComboNum (char[] arr, int index) { if (index == arr.length) return 1; if (arr[index] == '0') return 0; if (arr[index] == '1') { long res = getComboNum(arr, index+1) % mod; if (index + 1 < arr.length) { res += getComboNum(arr, index+2) % mod; } return res % mod; } if (arr[index] == '2') { long res = getComboNum(arr, index+1) % mod; if (index + 1 < arr.length && (arr[index+1] >= '0' && arr[index + 1] <= '6')) { res += getComboNum(arr, index+2) % mod; } return res % mod; } return getComboNum(arr, index+1) % mod; }*/ public static int dpComboNum(String strs) { if (strs == null || strs.charAt(0) == '0' || strs.length() == 0) return 0; int n = strs.length(); int[] dp = new int[n+1]; dp[n] = 1; for (int i = n-1; i >= 0; i--) { dp[i] = dp[i+1]; if (strs.charAt(i) == '0') dp[i] = 0; if (strs.charAt(i) == '1') { if (i + 1 < n) { dp[i] = (dp[i] + dp[i+2]) % mod; } } if (strs.charAt(i) == '2') { if (i + 1 < n && (strs.charAt(i+1) >= '0' && strs.charAt(i+1) <= '6')) { dp[i] = (dp[i] + dp[i+2]) % mod; } } } return dp[0]; } }
#include<iostream> #include<cstring> using namespace std; const int mod = 1e9+7; int proccess(string &s,int i) { if (i==s.size()) return 1; if (s[i] == '0') return 0; int res = proccess(s, i+1) % mod; if(i+1 < s.size()) { int num = (s[i]-'0')*10 + s[i+1]-'0'; if(num>=0 && num <=26) res = (res + proccess(s,i+2) ) % mod; } return res; } int main() { string s; cin>>s; int n = s.size(); if(s[0]==0) { puts("0"); return 0; } int res = proccess(s,0); cout << res << endl; }
#include<cstdio> (802)#include<cstring> const int mmax=100010; char str[mmax]; int dp[mmax]; int main(){ scanf("%s",str+1); dp[0]=1; if(str[1]!='0') dp[1]=1; //printf("%d",strlen(str+1)); for(int i=2;i<=strlen(str+1);++i){ if(str[i]!='0'){ dp[i]=(dp[i]+dp[i-1])%1000000007; } int sum=(str[i-1]-'0')*10+str[i]-'0'; if(sum>=10&&sum<=26){ dp[i]=(dp[i]+dp[i-2])%1000000007; } //printf("%d %d\n",i,dp[i]); } printf("%d",dp[strlen(str+1)]); }