这是递归方法很好的例子的值。让我们做一些定义,先
输入
输入小写的字符串,<'a','z'>
编码为<1,26>
无定界符。
输出
我们想要获得字符串的组合的所有解码每个有效解码1对2位代码。
启发式
所以2个代码可以用{ 1,2 }
就{ 0 }
意味着我们韩德林2位代码{ 10,20 }
或{ 0 }
为<0,25>
这可以用来降低组合数。
递归算法
如果我们有像decode(in);
一些函数,那么我们可以递归地做到这一点简单的方式是这样的:
decode (string in)
{
l=in.Length();
add_combination(tochar(in[1]) + in.substring(2,l-1));
add_combination(tochar(10*in[1]+in[2]) + in.substring(3,l-2));
}
在平原的话需要先1
或2
位字符并解码字符串的其余部分。让我们假设你的例子1125
的递归会像这样:
||decode(1125)|
|1|decode(125)|
|1,1|decode(25)|
|1,1,2|decode(5)|
|1,1,2,5|decode()| - combination
|1,1,25|decode()| - combination
|1,12|decode(5)|
|1,12,5|decode()| - combination
|11|decode(25)|
|11,2|decode(5)|
|11,2,5|decode()| - combination
|11,25|decode()| - combination
的intendation代表递归层,第一部分是当前组合的前缀(in0
)和右部分字符串的其余部分进行解码(in1+i
)。
这听起来很简单,但要编码这种反馈有点复杂。那是因为我们需要记住一个解决方案而不是一个解决方案。我决定将所有结果存储在由\r\l
行结尾分隔的单个字符串中。这里工作VCL/C++例如:
//---------------------------------------------------------------------------
AnsiString txt_encode0(const AnsiString &in) // <'a','z'> -> <0,25>
{
int i,l=in.Length();
AnsiString txt="";
for (i=1;i<=l;i++) txt+=int(in[i]-'a');
return txt;
}
//---------------------------------------------------------------------------
AnsiString txt_encode1(const AnsiString &in) // <'a','z'> -> <1,26>
{
int i,l=in.Length();
AnsiString txt="";
for (i=1;i<=l;i++) txt+=int(in[i]-'a'+1);
return txt;
}
//---------------------------------------------------------------------------
void txt_decode0(AnsiString &out,AnsiString in0,const AnsiString &in1,int i,int &l) // recursion <0,25> -> <'a','z'>
{
// stop recursion if whole string processed
if (i>l) { out+=in0+"\r\n"; return; }
int a0,a1;
// load first 2 digits from i if second digit is not applicable set is as -1
a0=in1[i]-'0'; i++;
if (i<= l) a1=in1[i]-'0'; else a1=-1;
if (a0> 2) a1=-1; // >2 means always 1 digit code
if (a0==0) a1=-1; // =0 means always 1 digit code
// one digit combination
in0+=char(a0+'a');
txt_decode0(out,in0,in1,i,l);
in0.SetLength(in0.Length()-1);
// 2 digit combination
if (a1>=0)
{
a0*=10;
a0+=a1; i++;
if (a0<=26)
{
in0+=char(a0+'a');
txt_decode0(out,in0,in1,i,l);
}
}
}
AnsiString txt_decode0(const AnsiString &in) // <0,25> -> <'a','z'>
{
int l=in.Length();
AnsiString in0="",out="";
txt_decode0(out,in0,in,1,l);
return out;
}
//---------------------------------------------------------------------------
void txt_decode1(AnsiString &out,AnsiString in0,const AnsiString &in1,int i,int &l) // recursion <1,26> -> <'a','z'>
{
// stop recursion if whole string processed
if (i>l) { out+=in0+"\r\n"; return; }
int a0,a1;
// load first 2 digits from i if second digit is not applicable set is as -1
a0=in1[i]-'0'; i++;
if (i<=l) a1=in1[i]-'0'; else a1=-1;
if (a0> 2) a1=-1; // >2 means always 1 digit code
// one digit combination
if (a1!=0) // =0 means always 2 digit code
{
in0+=char(a0+'a'-1);
txt_decode1(out,in0,in1,i,l);
in0.SetLength(in0.Length()-1);
}
// 2 digit combination
if (a1>=0)
{
a0*=10;
a0+=a1; i++;
if (a0<=26)
{
in0+=char(a0+'a'-1);
txt_decode1(out,in0,in1,i,l);
}
}
}
AnsiString txt_decode1(const AnsiString &in) // <1,26> -> <'a','z'>
{
int l=in.Length();
AnsiString in0="",out="";
txt_decode1(out,in0,in,1,l);
return out;
}
//---------------------------------------------------------------------------
void main()
{
AnsiString enc,dec,txt;
txt="decoding";
enc=txt_encode0(txt);
// enc="302213";
dec=txt_decode0(enc);
}
//---------------------------------------------------------------------------
的txt_encode0,txt_decode0
运行在<0,25>
和txt_encode1,txt_decode1
上<1,26>
范围内工作。
out
正在保存有效组合列表。 in0
包含组合的实际前缀in1
保存输入字符串。 i
是in1
和l
的实际组合的起始索引,长度为in1
。在这里,输出<0,25>
:
message:decoding
encoded:3421438136
decoded in [ 0.013 ms]
decbedibdg
decbeding
decodibdg
decoding
devedibdg
deveding
和您的样本:
encoded:302213
decoded in [ 0.007 ms]
daccbd
daccn
dacvd
dawbd
dawn
我使用AnsiString
从VCL他们从自身分配1
与索引动态字符串。例如AnsiString s="abc";
s[1]=='a'
它的大小是s.Length()
所以s[s.Length()]=='c'
。
工作要“提高”应该通过对[codereview.se]代码,但你应该可以肯定地说*你想要什么样的改进 - 执行时间?要么...? – AakashM
@AakashM因为我的算法似乎是以错误的方式进行的,并且必须有更好的方法,因为需要'output.indexOfArray(array)== - 1'来避免推送已存在于输出中的数组。 –
@Spektre但我不知道如何从一开始就写它。 –