题目:
假设数字和26个字母一一对应,即1对应a,2对应b......26对应z,给定一个字符串,按字典序返回,它可能与哪些字母串对应。
例如“11”可以对应为aa,k,ak,ka,
输入:数字串
返回:字典序的全部可与之对应的字母串。
PS:不知道为什么,家里的网络又抽了,继不能上百度、VC驿站、hao123等网站之后,发现连为学论坛也不能上了,所以只能手打题目了,链接没法贴上来了。
我的思路:
对于这种找所有的情况,最直接做法就是用回溯法找出所有解了。
1、对于长度nLen == 1的数字串来说,数字串中的数字只能有一种操作,就是直接找出该数值对应的字母。
2、对于长度nLen >= 2的数字串中每一个数字来说,数字串中的数字可以有两种操作。一,与1相同,直接找出该数值对应的字母;二、先不找出该数值的字母,与数字串下一个数字或者上一个数字组成2位10进制数,并找出对应的数字的字母。
3、根据第2点,依次递归、回溯即可找出所有的情况。
PS:代码实现中用到了栈来保存中间的结果。
时间复杂度应该,不太会分析~~~
#include<stdio.h>
#include<string.h>
const int N = 1000 ;
char chStack[N] ; //栈,保存中间结果
void Map(char* szNums,char* szChars,int index,int bOn,int nPre,int sp,int nLen) ;
void MapNums2Chars(char* szNums,char* szChars) ;
int main(void)
{
int i ;
char szNums[N] ;
char szChars[27] ;
freopen("in.txt","r",stdin) ;
for(i = 0 ; i < 26 ; ++i)
{
szChars[i+1] = 'a' + i ;
}
while(scanf("%s",szNums) != EOF)
{
MapNums2Chars(szNums,szChars) ;
printf("\n") ;
}
return 0 ;
}
void MapNums2Chars(char* szNums,char* szChars)
{
int nLen = strlen(szNums) ;
Map(szNums,szChars,0,0,0,-1,nLen) ;
}
//bOn ,0代表本层的操作是输出,1代表本层的操作是和上一层的数字组合成2位10进制数字并一起输出
void Map(char* szNums,char* szChars,int nIndex,int bOn,int nPre,int sp,int nLen)
{
if(nIndex >= nLen) //到数字串尽头,输出结果
{
chStack[++sp] = '\0' ;
printf("%s\n",chStack) ;
return ;
}
else
{
if(1 == bOn) //本层和上一层一起输出
{
chStack[++sp] = szChars[nPre*10 + (szNums[nIndex]-'0')] ; //和上一层一起输出
Map(szNums,szChars,nIndex+1,0,szNums[nIndex]-'0',sp,nLen) ; //下一层单独输出
chStack[sp] = '\0';
return ;
}
else if(0 == bOn) //本层单独输出
{
chStack[++sp] = szChars[szNums[nIndex]-'0'] ; //本层输出
Map(szNums,szChars,nIndex+1,0,szNums[nIndex]-'0',sp,nLen) ;//下一层单独输出
if(nIndex+1 < nLen && szNums[nIndex]-'0' < 3) //本层不输出,下一层和本层一起输出
{
chStack[sp] = '\0' ; //本层不输出
sp-- ;
Map(szNums,szChars,nIndex+1,1,szNums[nIndex]-'0',sp,nLen) ;
chStack[++sp] = szChars[szNums[nIndex]-'0'] ; //恢复本层输出
}
chStack[sp] = '\0' ;
return ;
}
}//else
}
我自己的测试数据:
1234
4321
112212
1312151267
11111
1111
111
1
PS:在论坛那里,看到别人用动态规则法解出来了,据说时间复杂度为O(n^2),太厉害了~~可能自己不太会动态规划的思想啊~~