考虑26个字母和10个数字的集合。
编写一个函数,返回长度为N的密码,其中包含至少L个小写字母,至少U个大写字母和至少D个数字。
功能签名 int cntPass(int N,int L,int U,int D)
我的方法:
我试图使用递归来解决它,但我认为它是错误的。我(错误的)重现如下:
F(N,L,U,d)= F(N,L-1,U,d)+ F(N,L,U-1,d)+ F(N,L,U,D- 1)[有必要的基础条件,但它没有工作]。
我正在寻找更好的方法或不同的逻辑来解决这个问题。
感谢。
答案 0 :(得分:5)
这只是一个简单的组合问题。结果是 N C L * NL C U * NLU C D * 26 L * 26 U * 10 D * 62 N - U - L - D ,可以简化为26 L + U * 10 D * 62 N - U - L - D * N! /(U!* L!* D!*(N - L - U - D)!)。
我们在N个地方为小写字符选择L个地方。然后在剩余的N - L位置中选择大写字母的U位置。并在剩余的N - L - U位置中选择D位数。其余的都有。
L小写字母各有26个选项。 U大写字母也是如此。 D位数各有10个选项。对于其余的(N - L - U - D),我们可以为每个人使用26 + 26 + 10个字符中的任何一个。
答案 1 :(得分:2)
@nhahtdh的答案是完全正确的。但是,如果需要大量数据,计算组合因子可能有点棘手(请参阅注释以获得良好的方法)。
这是一种计算相同数字而不通过阶乘的方法,但是使用递归:而不是将函数视为int cntPass(int N,int L,int U,int D),添加最后一个参数,表示可以是3中的任何一个的位数:
int cntPass(int N,int L,int U,int D,int A)
注意我们有A = N-L-U-D。 现在,递归基于第一个字符的选择:我们对小写有26个选择,大写有26个,数字有10个。
现在,给定N,L,U,D和A,可以
要结束递归,我们可以在N = 1时设置可能性的数量,或者在N = 0时等效地设置数量(到符号1)。
这是一个Matlab代码(用于快速测试的Matlab):
function [number]=Nword(N,LowerCase,UpperCase,Digit,Any)
number = 0;
if ( LowerCase > 0)
number = number + 26*Nword( N-1, LowerCase-1, UpperCase, Digit, Any);
elseif (Any > 0)
number = number + 26*Nword( N-1, LowerCase, UpperCase, Digit, Any-1);
end
if ( UpperCase > 0)
number = number + 26*Nword( N-1, LowerCase, UpperCase-1, Digit, Any);
elseif( Any > 0)
number = number + 26*Nword( N-1, LowerCase, UpperCase, Digit, Any-1);
end
if ( Digit > 0)
number = number + 10*Nword( N-1, LowerCase, UpperCase, Digit-1, Any);
elseif( Any > 0)
number = number + 10*Nword( N-1, LowerCase, UpperCase, Digit, Any-1);
end
if (number == 0)
number = 1;
end
return