最近在算法面试中有人问我这个问题,但未能解决。
给定两个值N和M,您必须计算长度为N的排列数目(使用1到N的数字),以使排列中任何数字与其排列中的位置之间的绝对差不等于M.
示例-如果N = 3且M = 1,则1 2 3和3 2 1是有效的排列,但1 3 2无效,因为数字3位于位置2且它们的差为=M。
我尝试了NxM动态编程,但没有形成不计入重复次数的重复发生。
最近在算法面试中有人问我这个问题,但未能解决。
给定两个值N和M,您必须计算长度为N的排列数目(使用1到N的数字),以使排列中任何数字与其排列中的位置之间的绝对差不等于M.
示例-如果N = 3且M = 1,则1 2 3和3 2 1是有效的排列,但1 3 2无效,因为数字3位于位置2且它们的差为=M。
我尝试了NxM动态编程,但没有形成不计入重复次数的重复发生。
Answers:
当给出这个问题时,我首先要问的是
您是否需要多项式时间算法?
然后我希望答案是“不”。我怀疑此问题是NP难题,原因如下:
解决此问题的自然方法是考虑第一个数字的位置并推导一个递归公式来放置其他数字。这对于情况非常有效(即计算错位的数量),因为您放置第一个数字的位置并不重要,因为每个数字只有一个“非法”位置。换句话说,这种方法导致了独立的子问题。
对于,这并不是那么简单,因为对于某些数字我们现在可以拥有非法头寸。这些位置中的哪一个保留在子问题中,现在与子问题的解决有关。仅考虑“非法”职位的数目是不够的,因为需要使用共享“非法”职位的数字“链”来确定该子问题的子问题的结构。因此,此方法实质上导致以下子问题:2
给定集合,集合的大小都为且自然数为,计算二部图,其中,当且仅当。乙⊆ Ñ Ñ 中号(甲,乙,ë )(一,b )∈ Ë | a − b | ≠ M
这个问题看起来很难。我看到的解决此问题的唯一方法是包含/排除,这不会导致多项式时间算法。
我们可以考虑不依赖于数字迭代放置的方法,但是我不知道您将如何进行。(尤其是在采访中!)
当然,所有这些仅仅是推测,并且仍然有可能巧妙的技巧可以提供多项式时间解,但是我希望我提出令人信服的论点,即该技巧确实必须非常聪明。
也许可以通过将问题简化为#2-SAT来显示NP硬度(共享非法位置的数字“链”似乎是不平凡的选择,可以与选择真值相匹配),但是到目前为止,我还没有发现一种明显的方法。
如果面试官实际上对指数时间算法感到满意,我将通过调整递归回溯算法以生成置换来排除此特殊情况,从而简单地生成所有可能的解决方案。
您是否可能记错了具体细节或对问题的理解有误?
在说明中,元件在位置被限制为。
但是,如果它们只是意味着差异受到限制:,
那么问题似乎很容易解决。b a − b ≠ ± M a − b ≠ M
我解决了这个较简单的问题,然后尝试以某种方式进行归纳,希望可以为解决较大的问题提供一些自由。但这为我澄清了为什么递归方法不太可能起作用,我将在最后讨论。
考虑函数,该函数给出标记为1到的元素列表的排列数量,其中位置(第一个位置为1)的元素满足和。
为了将其可视化,将其分为两个约束可以使和分别移动这些约束。
1 2 3 4 5 M=0, restricted values for each position
. . . . . (positions in list)
1 2 3 4 5 P=0, restricted values for each position
3 4 5 M=2, restricted values for each position
. . . . . (positions in list)
1 2 3 4 P=1, restricted values for each position
为方便起见,当不受排列限制时,定义。同样,当时,,因此对排列没有任何限制。
在特殊情况下,从约束和是等价的,因此可以被忽略,使我们能够写入来讲:
从问题的对称性来看:
让我们首先求解,然后解决更一般的。
对于,每个元素都有一个放置限制(并且这些限制是不同的)。因此,选择某些元素,我们将其放置在位置。选择有种不同的可能性。
此选择删除了元素的限制位置,而其他元素仍然具有一个限制。我们可以将的位置分为两个选项:
放在。这使所有其他元素受到一个限制,因此,剩余的放置问题现在减少为。
放在的位置。现在这给提供了一个放置限制,因此每个元素都有一个限制,剩下的放置问题减少到
因此,这给出了递归公式:
并且通过手工观察简单情况,可以获得基本情况。
这是通常的排列递归公式。
虽然我无法想象有人当场提出这个问题,但事实证明,有一个针对此问题的封闭式解决方案(有关详细信息,请参阅排列 Wiki文章)。
对于,对任何展示位置都没有限制:
当,前元素将没有限制,其余元素将有一个放置限制。就职位而言,最后的职位将允许所有数字。
对于最后一个位置,选择一个元素。剩余放置的外观有两种可能性:
如果,则没有放置限制,因此使用不会更改任何位置的限制。我们还无限制地删除了一个职位,因此剩余的位置看起来像。
如果,则有一个放置限制,并且我们无限制地删除了一个位置。因为被安置了,所以从现在开始它被限制的位置可以接受任何剩余的数字。因此,其余位置看起来像。
因此这给出了递归公式:
这样就完成了的递归解。
当,第一个位置具有单个数字限制,最后一个位置具有单个数字限制,而中间的位置没有限制。就像情况一样。
我们已经处理了当前除和之外的所有情况,使得。这是某些元素具有多个限制的地方。由于中的对称性,我们可以考虑而不会失去一般性。
前位置将具有单个限制,然后位置将具有两个限制,然后后位置将具有单个限制。
从元素上看,前元素具有单个限制,然后元素具有两个限制,然后后元素具有单个限制。
但是,这是我们必须结束的地方。由于这种方法没有前进的方向。
我分离了这两个约束,因为我看到将数字放置在选定的位置可能不平衡的“ +”约束和“-”约束有多少个单个约束位置。
但是,在更普遍的问题中,通过在其中放置数字来除去位置,并不总是会导致用描述的子问题。
为了可视化排列的这些约束,请考虑一个有向图,其中包含节点,一组标记为,另一组标记为。如果,则存在有向边如果且,则有向边。
可以将节点的集合视为我们在某些列表中排列的数字,而节点则视为它们的可能位置。该图表示约束。图中将没有周期。它始终是不相交的节点或长度为一或多个的链。
因此,我们需要一个函数作为约束图的输入,并输出满足约束的排列数量。
在的情况下,图仅是不相交的节点和单个边。因此,删除A和B节点将得到一个子图,该子图也是不相交的节点和单个边。
但是,对于,图可以具有长链。为了将数字放置在可用位置,无论我们固定节点还是固定位置,我们都需要考虑所有可能的构建方法的子图。分解链条的所有不同方式都会导致“递归”,每轮大约零件,因此与检查所有零件相比,节省不了多少排列。Ñ Ñ !
因为一旦允许使用链,可能会有很多子图,所以我真的看不到如何用通常的递归方法解决这个问题,除非有一个巧妙的关系说明非同构约束图在某种程度上等效于排列的数量。
我认为这个问题很可能被误解了。甚至可能由面试官(他们可能自己忘记了答案的详细信息)。