快速组合算法

时间:2018-10-18 04:07:27

标签: python

输入:给出var app = angular.module('myApp', []); app.controller('ctrl', function($scope, $http) { $http.get("data.json") .success(function (response) {$scope.state = response;}) .error(function (response) {alert("Error")}) }); items=[1,2,3],或者可以在values=[100,300,800]中。 查找所有组合项,以使总和值小于500

解决方案: dictionary={1:100,2:300,3:800} [1] [2] 必须对数百万个输入执行此操作。 WHat是实现此目标的最好,最快的算法?

4 个答案:

答案 0 :(得分:2)

import copy

dictionary = {
    100: 1,
    200: 2,
    800: 3,
}

value = sorted([100, 200, 800])

threshold = 500

res = []

def dfs(l, s, cur):
    if s < threshold:
        if len(l) > 0:
            res.append(l)
    else:
        return
    for i in range(cur + 1, len(value)):
        tmp = copy.copy(l)
        tmp.append(dictionary.get(value[i]))
        dfs(tmp, s+value[i], i)

dfs([], 0, -1)
print res

时间复杂度为O(K)。 K是正确结果的数量。

答案 1 :(得分:0)

在先过滤掉大于限制的值之后,您可以在压缩的项目和值序列上使用itertools.combinations

from itertools import combinations
items=[1,2,3]
values=[100,300,800]
def sums_less_than(items, values, limit):
    filtered = [(item, value) for item, value in zip(items, values) if value < limit]
    return [[item for item, _ in c] for n in range(1, len(filtered) + 1) for c in combinations(filtered, n) if sum(value for _, value in c) < limit]
print(sums_less_than(items, values, 500))

这将输出:

[[1], [2], [1, 2]]

答案 2 :(得分:0)

经过修改:

import copy

dictionary = {
    100: 1,
    200: 2,
    800: 3,
    50 : 4,
}

value = sorted(dictionary.keys())

threshold = 500

res = []
thres_val=[]


def dfs(l, s, cur):
    if s < threshold:
        if len(l) > 0:
            res.append(l)
            thres_val.append(s)
    else:
        return
    for i in range(cur + 1, len(value)):
        tmp = copy.copy(l)
        tmp.append(dictionary.get(value[i]))
        dfs(tmp, s+value[i], i)

dfs([], 0, -1)
print(res)
print(thres_val)

print("\tItem list-->Value")
j=0
for i in res:
    print("\t",i,"-->",thres_val[j])`

答案 3 :(得分:0)

一种更有效的方法是使用广度优先搜索,如果当前项目值加上当前总和已经达到限制,则进一步避免排队,以便在{ {1}}和限制[1, 2, 3, 4, 5],如果当前值组合为5并且当前项目值为[1, 2],则由于我们发现3已经存在不少于1 + 2 + 3,我们不会排队5进行进一步搜索。这大大减少了我们需要测试的组合数量:

[1, 2, 3]

这样:

from collections import deque
def sums_less_than(items, values, limit):
    seeds = [(index, 0, [], item_value) for index, item_value in enumerate(zip(items, values))]
    queue = deque(seeds)
    while queue:
        index, _sum, combination, (item, value) = queue.popleft()
        new_sum = _sum + value
        if new_sum < limit:
            new_combination = combination + [item]
            yield new_combination
            for i in range(index + 1, len(seeds)):
                queue.append((i, new_sum, new_combination, seeds[i][-1]))

将输出:

items=[1,2,3]
values=[100,300,800]
print(list(sums_less_than(items, values, 500)))