具有特定约束的长度为N的密码数

时间:2013-02-04 10:53:09

标签: algorithm math recursion logic combinatorics

考虑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)[有必要的基础条件,但它没有工作]。

我正在寻找更好的方法或不同的逻辑来解决这个问题。

感谢。

2 个答案:

答案 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,可以

  • 将小写字母作为第一个字符 - > 26种可能性。对于这些可能性中的每一种,我们对其余密码都有cntPass(N-1,L-1,U,D,A)可能性。注意如果L = 0,则不起作用,除非 A> 0,即仍有一些字符可供选择。在这种情况下,我们还有26种可能性,每种情况都有cntPass(N-1,L,U,D,A-1)。
  • 同意大写
  • 数字同意。

要结束递归,我们可以在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