簡體   English   中英

給定總和的最短子集和Python中最快的解決方案

[英]Shortest subset for given sum and fastest solution in Python

這是“給定和問題”的一個變體,我嘗試用Python編寫一個解決方案,該解決方案將在O(log n)時間內解決。 對於給定的自然數N (equal or larger than 1)找到項p 1..n的最短計數,這些和使N ,並且p項是以下迭代的乘積:

p i值是p i-1 * 2p i-1 + 1

p 1開始,恰好是1

因此:

p 2始終為2,但p 3可以為3或4

對於輸入N = 18 ,候選集為:[1、2、4、5、6],[1、2、3、4、8],[1、2、4、5、6],[1, 2,3,4,8]

answer is 5

到目前為止,這是我編寫的代碼,但運行緩慢,並且凍結在中等“大”(N> = 1000)值上:

possible = None


def solution(N):
    global possible
    possible = list()
    tea(1, [1], N)
    sizes = [len(p) for p in possible]
    return min(sizes)
    pass


def tea(n, l, target):
    global possible
    if (sum(l) > target):
        return
    elif (sum(l) == target):
        possible.append(l)
    i = n * 2
    tea(i, l + [i], target)
    i = n + 1
    tea(i, l + [i], target)

print solution(18)
# should print 5
print solution(220)
# should print 11
print solution(221)
# no such solution? print -1

如何以更有效的方式解決它?

最快的解決方案是最關鍵的,但是也需要更多的Python代碼。

使用廣度優先搜索來減少浪費的精力。 下面的代碼可以進一步優化。

def solution(n):
    q = [(1,)]
    visited = set()
    for seq in q:
        s = sum(seq)
        if s == n:
            return seq
        elif s > n:
            continue
        key = (seq[-1], s)
        if key in visited:
            continue
        visited.add(key)
        q.append(seq + (seq[-1] * 2,))
        q.append(seq + (seq[-1] + 1,))
    return None

您正在尋找最短的解決方案,因此,如果找到了解決方案,則無需尋找更長的解決方案。
您可以更改代碼,以使它不會再以這種方式找到解決方案:
(注意條件是否添加)

def tea(n, l, target):
    global possible
    if (sum(l) > target):
        return
    elif (sum(l) == target):
        possible.append(l)

    # we want to keep looking for new solutions only if l is shorter!
    if possible and (len(l) >= max(len(i) for i in possible)):
        return

    i = n * 2
    tea(i, l + [i], target)
    i = n + 1
    tea(i, l + [i], target)

另外,似乎您希望函數在沒有解決方案時返回-1 ,目前,您的代碼在這種情況下會引發錯誤,我將solution()函數更改為:

possible = []

def solution(N):
    global possible
    tea(1, [1], N)
    sizes = [len(p) for p in possible] # you can use: size = map(len,possible) instead
    if sizes:
        return min(sizes)
    return -1

至於您的“更多pythonic代碼”,我會這樣寫:

def solution(N):
    possibles =[]
    tea(1, [1], N, possibles)
    if not possibles:
        return -1
    else:
        return min(map(len,possibles))

def tea(n, l, target, possibles): # maybe a better name then "tea"
    if (sum(l) > target):
        return
    elif (sum(l) == target):
        possibles.append(l)
        return
    if possibles and (len(l) >= max(len(i) for i in possibles)):
        return
    tea(n * 2, l + [n * 2], target, possibles)
    tea(n + 1, l + [n + 1], target, possibles)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM