从数组A中找到最短数字序列的算法,加起来为数字B

时间:2018-02-04 22:30:26

标签: algorithm

前几天我有一个有趣的面试问题,这让我很难过。我无法找到一个非常好的答案。问题所在:

  

假设您有一个数字 B 和一个长度为n的数组 A 。数字B是一个自然数,数组 A 中的所有数字都是不同的自然数。设计一种算法,该算法可以在数组 A 中找到最短的数字序列,总计数字 B 。可以使用重复项。

因此,举个例子,我们假设我有一个B = 19A = [9, 6, 3, 1]。我可以说解决方案是6+6+6+13+3+3+3+3+3+1,但他们正在寻找的解决方案是9+9+1,因为这是最短的数字序列。

我设计的算法会对数组进行排序并达到最大数字并从原始数字中减去它。它将继续这样做,直到它不再减去最大的数字。然后它将通过数组,看看它是否可以继续找到它可以从B中减去的任何数字。它实际上看起来很像这样:

def domath(b, a):
    a.sort()
    x = []
    n = 0
    idx = -1
    while b != 0:
        n = a[idx]
        if(b >= n):
            b -= n
            x.append(n)
        else:
            idx -= 1
    return x

但这种解决方案并不总是有效。只有当你足够幸运地拥有阵列中的2或1,或者你从b中减去的数字神奇地工作时,它才会起作用。考虑B=21A=[7,8,9]。如果它继续减去9,它将无法找到解决方案。

所以我在思考"好吧,那么也许我需要回溯一下。"。

如果我进入x数组,跟踪我们减去的所有数字,我可以添加从b中减去的最新数字,然后尝试将idx移到< em> next 最大的数字。所以,而不是做21 - 9,然后12 - 9,它会做21 - 9,然后12 - 8.它仍然找不到任何东西,所以它会尝试21 - 9,然后12 - 7.它仍然不会找到什么,所以它会尝试21 - 8,然后13 - 8,它不会找到任何东西,所以它会做21 - 8,然后13 - 7,它仍然不会找到任何东西,所以它会尝试21 -7,并继续,并确定它是否可以做到这一点。如果它不能(在这种情况下,它应该),它只会返回&#34; False&#34;什么的。

那是......一个很好的解决方案吗?我觉得必须有一个更好的,因为面试官对这个解决方案有点不确定。

1 个答案:

答案 0 :(得分:0)

棘手。链接的维基百科页面提出了一种方法,我认为O(B *长度(A))如果我们有B = 1,000,000,000,000而不是B = 21而A = [9,8,7]则需要很长时间。如果你从一个部门开始,你的回溯算法会很快地处理这个问题:

111,111,111,111 nines leaves one, no way. 
111,111,111,110 nines leaves ten, no way (trying 1 or 0 eights)
111,111,111,109 nines leaves 19, no way (trying 2, 1 or 0 eights)
111,111,111,108 nines leaves 28 = 4x7 (trying 3 .. 0 eights). Best so far.
111,111,111,107 nines leaves 37. 4x8 < 37, no solution can beat what we have.

在你的例子中,B = 21,回溯也会很好。如果我们只是表示九,八和七的数量,那么你只需要尝试以下内容:2,0,0; 1,1,0; 1,0,1; 0,2,0; 0,1,1; 0,0,3。

当您有解决方案时,您希望停止搜索分支,并且可以证明没有其他解决方案可以更好。这就是我所做的:当你剩下37个并且可用的最高数量是8时,你需要至少5个数字。对于你删除的每九个这个数字至少增加一个,所以到目前为止最好的解决方案不能被打败。