算法的正确性证明

时间:2014-05-22 07:09:13

标签: algorithm

我们的老师问我们一个类似的问题。

Given a list of n distinct integers and a sequence of n boxes with preset
inequality signs inserted between them, design an algorithm that places
the numbers into the boxes to satisfy those inequalities. For example, the
numbers 2, 5, 1, and 0 can be placed in the four boxes as shown below 

从查看问题我们可以说数字被排序,如果接下来出现小于符号,我们必须插入最小数字,如果出现大于符号,我们必须插入最大数字并继续进行。

  1. 我怎么能说这个算法适用于每种情况?
  2. 穿越 一个方向我找到了一个解决方案,并且我找到了相反的顺序 另一个。找到所有解决方案的有效方法是什么? 问题?

3 个答案:

答案 0 :(得分:3)

为了回答问题1,我说应该通过归纳所涉及的不同数字来完成。

n是数字的数量。

对于n = 1,没有什么可以证明的。

对于n = 2,您有一个大于或小于运算符。由于数字是不同的,并且自然(或真实)数字的集合排序很好,因此您的算法将很容易产生解决方案。

n -> n+1: 情况1:第一个运算符小于符号。根据您的算法,您选择最小的数字并将其放入第一个框中。然后解决最后n个框的问题。这可以通过归纳来实现。由于第一个框中的数字最小,因此它也小于第二个框中的数字。因此,你有一个解决方案。

案例2:第一个运算符大于号。这也与案例1类似。

QED

现在问题的第二部分。我想出了下面描述的算法。很高兴我首先解决了问题(获得所有解决方案),但我无法保证它是最快的解决方案。

正如评论中已经指出的,如果没有操作员更改,则只有一个解决方案。所以我们假设有运算符更改(但算法也会生成此解决方案)。

for all operator changes of the form >< or nil < (first operator is a <):
    place the smallest element between them
    now divide the remaining set of numbers into two.
    if there are n numbers and there are k operators to the left of 
    the placed number, that will give you k over (n - 1) possibilities.
    do this recursively with the two remaining parts.

If no operator changes of the form >< or nil < are left, 
do the same with the mirrored operator changes <> and nil >, 
but choose the highest element of the set.

If no operator changes are left, fill in the elements according to the 
remaining operator in ascending or descending order.

好的,这不是程序代码,但我认为这将相对容易(n - 1中的选择k是困难部分)。我希望我对算法的解释是可以理解的。请注意,解决方案的数量增长很快(指数级,可能更糟)。

答案 1 :(得分:1)

部分回答问题的第二部分,找到一个单一的解决方案:

首先,可以对输入进行排序,这可以在O( n log n )时间内完成。然后,可以应用所描述的算法;最小和最大元素位于列表的开头和结尾,可以在固定时间内访问。这意味着,一旦对输入进行排序,就可以在O( n )时间内生成输出。这总共产生了O( n log n )的运行时限制。

答案 2 :(得分:1)

以下是 将数字分配给方框的证明:

  

该图定义了空盒子上的部分顺序(方框A&lt; =方框B   如果A = B,或A是B的左边,那么只有&lt;它们之间,   或者A在B的右边,并且只有&gt;它们之间)。这很简单   检查&lt; =是否满足部分订单的属性。

     

任何有限的部分有序集都可以完全有序(例如   通过使用拓扑排序)。

     

然后根据总订单对框进行排序,并分配数字   根据结果​​列表中的位置。

这会得到问题第(2)部分的答案,即列举所有可能的解决方案。解决方案恰好是与校对中定义的部分顺序兼容的总订单,您可以通过选择拓扑排序算法中每个阶段选择的最小元素来生成所有可能的总订单。

也就是说,您可以生成以下所有解决方案:

topo_sort(boxes):
    if boxes = [] then return [[]]
    let result = []
    for each x in minimal(boxes)
        for each y in topo_sort(boxes - x)
            append ([x] + y) to result
    return result

minimal(boxes):
    return [all x in boxes such that there's no y != x in boxes with y lesseq x]

这里“lesseq”的构造与证明相同。

如果您足够眯眼,您可以看到您的算法也可以被视为拓扑排序算法,使用观察结果,如果下一个符号是&gt;那么第一个元素在剩余列表中是最大的,并且如果下一个符号是&lt;然后第一个元素在剩余列表中是最小的。该观察结果可以证明您的算法也是正确的。

这是一个低效的Python 2.7实现:

def less(syms, i, j):
    if i == j: return False
    s = '<' if i < j else '>'
    return all(c == s for c in syms[min(i,j):max(i,j)])

def order(boxes, syms):
    if not boxes:
        yield []
        return
    for x in [b for b in boxes if not any(less(syms, a, b) for a in boxes)]:
        for y in order(boxes - set([x]), syms):
            yield [x] + y

def solutions(syms):
    for idxes in order(set(range(len(syms)+1)), syms):
        yield [idxes.index(i) for i in xrange(len(syms)+1)]

print list(solutions('<><'))

其中输出所有5个解决方案:

[[0, 2, 1, 3], [0, 3, 1, 2], [1, 2, 0, 3], [1, 3, 0, 2], [2, 3, 0, 1]]