这个算法有O(N)解决方案吗?

时间:2017-06-16 16:06:30

标签: python algorithm sorting search

包括副本和反向有序对,它们加起来总和

numbers = [1, 2, 4, 4, 4, 4, 5, 5, 5, 7, 7, 8, 8, 8, 9]

match = []
for i in range(len(numbers)):
    for j in range(len(numbers)):
        if (i!=j):
            if(numbers[i] + numbers[j] == sum):
                match.append([numbers[i], numbers[j]])

我需要检查匹配项和重复项,因此输出需要看起来像[[1, 9], [2, 8], [2, 8], [2, 8], [5, 5], [5, 5], [5, 5], [5, 5], [5, 5], [5, 5], [8, 2], [8, 2], [8, 2], [9, 1]]

3 个答案:

答案 0 :(得分:0)

这是一个变种:

from collections import Counter


def sum_target(lst, target):

    unique_list = list(set(lst))
    counts = Counter(lst)

    remainders = {number: target-number for number in unique_list}

    match = set()
    for a, b in remainders.items():
        if b in remainders:
            match.add(tuple(sorted((a, b))))

    # restore multiplicities:
    ret = []
    for a, b in match:
        if a != b:
            mult = counts[a] * counts[b]
            ret.extend([a, b] for _ in range(mult))
            ret.extend([b, a] for _ in range(mult))
            # ret.append((mult, (a, b)))
            # ret.append((mult, (b, a)))
        else:
            mult = counts[a] * (counts[a]-1)
            ret.extend([a, a] for _ in range(mult))
            # if mult != 0:
                # ret.append((mult, (a, b)))

    return ret

并不完全确定多重性是按照你想要的方式处理的(在你的例子中它们是我得到的两倍......为什么有[5, 5]的6个版本?你的三个5 s原始列表你只得到3双......)

如果您的列表中有许多重复项,那么根据您的输出长度,我建议将代码的最后一部分更改为

# restore multiplicities:
ret = []
for a, b in match:
    if a != b:
        mult = counts[a] * counts[b]
        ret.append((mult, (a, b)))
        ret.append((mult, (b, a)))
    else:
        mult = counts[a] * (counts[a]-1)
        if mult != 0:
            ret.append((mult, (a, b)))

获得结果

numbers = [1, 2, 4, 4, 4, 4, 5, 5, 5, 7, 7, 8, 8, 8, 9]
s = 10
print(sum_target(lst=numbers, target=s))
# [(3, (8, 2)), (3, (2, 8)), (6, (5, 5)), (1, (1, 9)), (1, (9, 1))]

答案 1 :(得分:0)

正如评论中提到的那样,对于一般情况没有O(n)解决方案,因为在最坏的情况下,您需要输出n^2个数字对 - 显然它不能在{{{}}中完成1次。但是当阵列中没有相同的数字时,有线性解决方案,你只需要使用字典:

O(n)

答案 2 :(得分:0)

In[50]: numbers
Out[50]: [1, 2, 4, 4, 4, 4, 5, 5, 5, 7, 7, 8, 8, 8, 9]
In[51]: expected_result
Out[51]: 
[[1, 9],
 [2, 8],
 [2, 8],
 [2, 8],
 [5, 5],
 [5, 5],
 [5, 5],
 [5, 5],
 [5, 5],
 [5, 5],
 [8, 2],
 [8, 2],
 [8, 2],
 [9, 1]]
In[52]: from collections import Counter
   ...: 
   ...: 
   ...: def matches(nums, target):
   ...:     cnt = Counter(nums)
   ...:     result = []
   ...:     for num in nums:
   ...:         diff = target - num
   ...:         result.extend([[num, diff]] * (cnt[diff] - (diff == num)))
   ...:     return result
   ...: 
In[53]: matches(numbers, target=10) == expected_result
Out[53]: True