给出一个数字列表L = {a1,a2,a3,a4,...,aN}
问题是将这个 L 分成两部分,不仅仅是一次,而是递归,直到它变成原子。主要思想就像this post,但添加了递归的东西。
(已添加:6月9日) 例如,如果我们有L = {10,20,1,2} (已编辑:6月10日)< / em>解决方案可能首先将其除以{10,1,2}和{20},然后将前者划分为{1,2}和{10},继续{1,2}转到{ 1},{2}。现在L的所有成员现在原子不再被分割了。
分割后,它应该看起来像某种二叉树。
让我们说它看起来像这样......
(a1 a2 a3 a4)
/\
/ \
/ \
/ \
(a1 a2) (a3 a4)
/\ /\
/ \ / \
(a1)(a2)(a3)(a4)
在每个节点处,相似度函数是
abs( sum(left_child) - sum(right_child) ) / sum(itself)
我想找一个&#34;优化&#34;根据&#34;求和&#34;划分列表(创建树)的方法此功能。请注意,在顶层,此值可能比较低的值具有更大的影响,因此应提供权重。
weight(level) * abs( sum(left_child) - sum(right_child) ) / sum(itself)
让级别是二叉树中此节点的级别。
我认为可以使用动态编程来解决这个问题,时间复杂度为O(2 ^ N)。但是,这个解决方案对我来说似乎太慢了。有谁有更好的解决方案?
欢迎优化和近似。
提前谢谢。
答案 0 :(得分:0)
O(n)时间复杂度但真正不准确的方法是:
def distance(a, b):
return abs(a - b)
def balancedSlice(myList):
total = sum(myList)
a = 0 #a, b are the sum's of each slice
b = total
dist = distance(a, b) # current distance between slices
for i in range (len(myList)):
a += myList[i]
b -= myList[i]
if dist <= distance(a, b):
return myList[:i],myList[i:] #list sliced "from 0 to before i" and "from i to end"
dist = distance(a, b)
O(n log n)中另一个更准确但不完美的贪心算法:
def balancedSlice(myList):
list1 = list()
list2 = list()
myList = list(myList) #skip if you can destroy the original list.
myList.sort() # O(n log n)
while myList:
item = myList.pop()
if sum(list1) <= sum(list2):
list1.append(item)
else:
list2.append(item)
return list1, list2
然而,正如here所述,这是一个NP问题,所以如果你的列表足够大并且你可以容忍不完美的结果,你应该坚持使用这种贪婪算法。