在给定N-1个约束的情况下,计算小于整数N的数字的可能排列数

时间:2013-02-11 10:15:11

标签: c++ algorithm

我们得到一个整数N,我们需要计算小于N的数字排列总数。我们也给出了N-1个约束。 e.g:

如果N=4则计算0,1,2,3给出的排列:

0>1
0>2
0>3

我考虑制作一个图表,然后计算同一级别的数字排列的总数,并将其乘以其他级别的排列。例如:

对于上面的例子:

             0
           / |  \
          /  |   \
         1   2    3 ------> 3!=6 So total no of permutations are 6.

但我很难在C++中实施它。此外,这个问题在Facebook黑客杯中被问到,竞争已经结束了。我见过其他人的代码,发现他们是使用DFS完成的。有什么帮助吗?

1 个答案:

答案 0 :(得分:2)

最简单的方法是使用标准排列生成器并过滤掉违反条件的每个排列。这显然是非常低效的,并且对于较大的N值是不可计算的。这样做是一种“诱杀”选项,这些选项让不太聪明的参赛者能够完成这个问题。

熟练的方法需要深入了解计算组合和排列的方法。为了说明方法,我将使用一个例子。输入:

   N = 7  
   2 < 4  
   0 < 3  
   3 < 6  

我们首先通过将依赖条件组合成单个条件来简化这一过程,如下所示:

   2 < 4  
   0 < 3 < 6  

从最长条件开始,并确定间隙的组合计数(这是关键洞察力)。例如,一些组合如下:

   XXXX036  
   XXX0X36  
   XXX03X6  
   XXX036X  
   XX0XX36  
   etc.  

现在,您可以看到有4个差距:? 0? 3? 6?我们需要在这四个空白中计算X的可能分区。这样的分区数是(7选3)= 35(你明白为什么?)。现在,我们接下来乘以下一个条件的组合,即2&lt; 4剩余的空白点(Xs)。我们可以相乘,因为这个条件完全独立于0 <3 <6条件。这个组合计数是(4选2)= 6.最终条件有2个值= 2的2个值! = 2.因此,答案是35 x 6 x 2 = 420。

现在,让它变得更复杂一些。添加条件:

   1 < 6

这改变计算的方式是在036之前必须按此顺序出现。但是,现在,我们有三种可能的安排:

   1036  
   0136  
   0316  

因此,现在总计数(7选4)x 3 x(3选2)= 35 x 3 x 3 = 315.

因此,回顾一下,程序是将问题隔离到独立的条件中。对于每个独立条件,您计算分区的组合,然后将它们相乘。

我已经手动完成了这个示例,但您可以编写相同的程序。