【问题标题】:Use python to solve a math problem: sum up to a value as close as possible用python解决一道数学题:求和一个尽可能接近的值
【发布时间】:2018-11-24 00:32:46
【问题描述】:

我有一个数字列表。现在如果我设置一个固定值V,python是否可以将列表分成几组,使得每组的总和不小于V(尽可能多地获得这些组)?

例如:如果列表是 [1,2,3,4,5] 并且 V 是 6,那么结果应该是 [[1,5],[2,3,4]]。分组意味着您不能多次使用相同的原始项目。

每个子列表可以包含多少个项目没有限制,并且数字也不是按顺序排列的(可以是一些随机数)。有人可以帮我吗?到目前为止,我的解决方案是总结所有组合并比较总和。但我很确定应该有更有效的解决方案。谢谢!

我的解决方案:我有点先使用它,然后在我的脑海中完成其余的工作,所以它不值得进一步开发。

import itertools
import math

stuff = list(range(10))
v = 6

for L in range(0, len(stuff)+1):
    for subset in itertools.combinations(stuff, L):
        if math.fsum(subset) > v: 
            print(subset,math.fsum(subset))

【问题讨论】:

  • 你能把你的解决方案显示为代码吗?
  • @RoryDaulton 是的,我只是注意到了这一点。我改变了我的描述。谢谢!
  • 但是,根据你的描述,这3个不应该是分开的
  • @user8408080 你是对的

标签: python list math sum


【解决方案1】:

我的解决方案具有 O(n^2) 时间复杂度。您可以按升序对列表进行排序。然后从末尾迭代列表。由于您想要最大数量的子集,然后每个大于 V 的值都添加到数组中。在其他情况下,从左右角收集值,同时实现子集的总和等于 V:

def get_value_in_dict(d):
    return d.get(list(d)[0])

# Implementation for a list of dictionaries like [{'apple':1},{'pear':22},{'hat':23},{'glass':44}]
def sum_up_to_value(stuff, val):
    new_stuff = []
    sorted_stuff = list(sorted(stuff, key=lambda el: get_value_in_dict(el)))
    n = len(stuff)
    pointer_r = n - 1
    pointer_l = 0
    queue = list()

    while pointer_r >= pointer_l:
        if get_value_in_dict(sorted_stuff[pointer_r]) >= val:
            new_stuff.append([sorted_stuff[pointer_r]])
        else:
            subsum = get_value_in_dict(sorted_stuff[pointer_r])
            substuff = []
            while pointer_l < pointer_r and subsum < val:
                # get from queue
                while len(queue) and subsum < val:
                    temp = queue.pop(0)
                    subsum += get_value_in_dict(temp)
                    substuff.append(temp)
                # get from input
                else:
                    if subsum < val:
                        subsum += get_value_in_dict(sorted_stuff[pointer_l])
                        substuff.append(sorted_stuff[pointer_l])
                        pointer_l += 1
            substuff.append(sorted_stuff[pointer_r])
            # returns back smallest elements
            while subsum - get_value_in_dict(substuff[0]) >= val:
                temp = substuff.pop(0)
                queue.append(temp)
                subsum -= get_value_in_dict(substuff[0])

            if subsum < val:
                # add substuff to last element of new_stuff
                temp = new_stuff.pop()
                new_stuff.append(temp + substuff)
            else:
                new_stuff.append(substuff)
        pointer_r -= 1
    return new_stuff  # list(map(lambda el: sorted(el, key=lambda el_d: get_value_in_dict(el_d)), new_stuff)) for sorted by value elements in resulting list

【讨论】:

  • 其实对于[1,2,3,4,5]和V=6,我需要[[1,5],[2,3,4]]或者[[1,3, 5],[2,4]] 因为 3 小于 6 所以它本身不能是一个子列表。
  • @LouieLee,我为您的新要求添加了一些代码
  • 太棒了!但是,是否可以在项目为 dict 的列表上做同样的事情,比如 [{'apple':1},{'pear':22},{'hat':23},{'glass':44} ] 有 [[{'apple':1},{'glass':44}],[{'pear':22},{'hat':23}]]?谢谢
  • @LouieLee,刚刚编辑了字典列表的代码。刚刚添加了一个在 dict 中获取价值的函数。在 Python 3.6 中工作
  • @LouieLee,如果您对此解决方案满意,请将此答案标记为有用。
【解决方案2】:

如果你对你的列表进行排序,这应该会得到你想要的结果,尽管我不得不承认它不是很漂亮:

stuff = range(10)
l = len(stuff)
v = 6

new_stuff = []
i = 0
active = True

while active:
    sub_stuff = []
    subsum = 0
    while subsum<v:
        if i>(l-1):
            active = False
            break
        el = stuff[i]
        sub_stuff.append(el)
        subsum += el
        i += 1
    else:
        new_stuff.append(sub_stuff)

它只是遍历您的列表并对元素求和,直到它们的总和为 6 或更高,然后将这些元素的列表附加到 new_stuff 并继续查找下一个列表。

尝试如下测试列表:

import numpy as np
stuff = sorted(np.random.randint(0,10,100))

【讨论】:

  • 您可以将 while subsum
  • 另外,如果我有 stuff = [44,23,22,1] 和 v = 45,您的代码会生成 [[44, 23]] 而不是 [[44,1],[23 ,22]]
  • 如果 stuff = [1,22,23,44] 和 v = 45,您的代码将生成 [[1, 22, 23]] 而不是 [[44,1],[23,22 ]]
  • 是的,你是对的;这个算法太简单了。也许我明天可以想出更好的东西
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多