簡體   English   中英

查找長度為n的列表的k個元素,它們在O(nlogk)時間之內的總和小於t

[英]Finding k elements of length-n list that sum to less than t in O(nlogk) time

這是《 Programming Pearls》編輯的。 2,第2欄,問題8:

給定一組n個實數,一個實數t和一個整數k,您可以多快確定是否存在該集合的k個元素子集,總和最多為t?

一個簡單的解決方案是對前k個元素進行排序和求和,這是我們找到此類和的最大希望。 但是,在解決方案部分中,Bentley提到需要花費nlog(k)時間的解決方案,盡管他沒有提供有關如何找到它的提示。 我一直在為此苦苦掙扎; 我曾經想過要遍歷列表,並添加所有少於t / k的元素(以O(n)時間計); 假設有m1 <k個這樣的元素,它們的和等於s1 <t。 然后我們剩下k-m1個元素,因此我們可以在O(n)時間內再次掃描列表,以查找所有小於(t-s1)/(k-m1)的元素。 再次相加,得到s2和m2,如果m2 <k,則再次查找小於(t-s2)/(k-m2)的所有元素。 所以:

def kSubsetSumUnderT(inList, k, t):
    outList = []
    s = 0
    m = 0
    while len(outList) < k:
        toJoin = [i for i in inList where i < (t - s)/(k - m)]
        if len(toJoin):
            if len(toJoin) >= k - m:
                toJoin.sort()
                if(s + sum(toJoin[0:(k - m - 1)]) < t:
                    return True
                return False
            outList = outList + toJoin
            s += sum(toJoin)
            m += len(toJoin)
        else:
            return False

我的直覺是,這可能是O(nlog(k))算法,但是我很難向自己證明。 思考?

考慮以下示例,其中t> 0和all([x>t for x in inList]) toJoin將始終為空,並且您的算法甚至無法完成,更不用說O(nlog(k))了。

您可能缺少的提示是http://en.wikipedia.org/wiki/Heap_(data_structure)

運行時間Theta(n log k)的自然算法可能是初始化具有k個無窮大的max-heap,然后遍歷數組,推送新元素並彈出max,最后將k留在堆中最少。 (正如Bentley提到的那樣,在Theta(n)時選擇速度漸近。在實踐中,最好的選擇方法是將最小的k次堆放並彈出,這是Theta(n + k log n)= Theta(n)當k = O(n / log n)時。)

暫無
暫無

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

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