简体   繁体   English

从4个给定的数组(未排序)中,找到每个数组的元素,其总和等于某个数字X.

[英]From 4 given arrays(not sorted), find the elements from each array whose sum is equal to some number X

Suppose there are 4 unsorted arrays as given below: 假设有4个未排序的数组,如下所示:

A = [0, 100, -100, 50, 200]
B = [30, 100, 20, 0]
C = [0, 20, -1, 80]
D = [50, 0, -200, 1]

Suppose X is 0, so the few of the possible O/P should be (pick 1 element from each array which satisfy condition): 假设X为0,那么可能的O / P应该是少数(从每个满足条件的数组中选择1个元素):

0,0,0,0
-100, 100, 0, 0
-100, 30, 20,50 .. etc.

I was able to devise the algorithm which can do this in O(n^3LogN), is there any better way to achieve the same? 我能够设计出可以在O(n ^ 3LogN)中执行此操作的算法,有没有更好的方法来实现相同的目标?

My Solution: 我的解决方案

1- Sort each array. 1-排序每个阵列。

2- Fixed the element from array A. 2-修复了阵列A中的元素。

3- run three loops for the rest of the arrays and take the sum of each element: 3-为其余数组运行三个循环并获取每个元素的总和:

if sum > 0 (return -1, no such elements exit)

if sum == 0 (return current elements)

if sum < 0 (then advance the pointer from the array for which the current element is minimum.)

Any suggestion over this? 有什么建议吗?

Assuming your arrays all have the same length n (+/- some constant value) you can get O(n^3) by using a set for the fourth array: 假设你的数组都具有相同的长度n (+/-某个常数值),你可以通过使用第四个数组的set得到O(n^3)

from itertools import product

ds = set(D)
for a, b, c in product(A, B, C):
    d = X - a - b - c
    if d in ds:
        print(a, b, c, d)

If one or multiple arrays contain (many) extreme values you can also take shortcuts by checking the running sum against the min and max of subsequent arrays to see if X can still be reached. 如果一个或多个数组包含(许多)极值,您还可以通过检查后续数组的minmax的运行总和来查看快捷键,以查看是否仍然可以访问X For example: 例如:

ds = set(D)
c_min, c_max = min(C), max(C)
d_min, d_max = min(ds), max(ds)
for a in A:
    for b in B:
        s = a + b
        if s + c_min + d_min > X or s + c_max + d_max < X:
            continue  # Shortcut here.
        for c in C:
            d = X - a - b - c
            if d in ds:
                print(a, b, c, d)

You can further extend this by storing solutions that have already been found for a running sum (of the first two arrays for example) and hence taking a shortcut whenever such a sum is encountered again (by reordering with the min/max check one can avoid repeated computation of s + min/max values): 您可以通过存储已经找到的运行总和(例如前两个数组)的解决方案来进一步扩展这一点,并因此在再次遇到这样的总和时采用快捷方式(通过使用最小/最大检查重新排序可以避免重复计算s + min / max值):

ds = set(D)
c_min, c_max = min(C), max(C)
d_min, d_max = min(ds), max(ds)
shortcuts = {}
for a in A:
    for b in B:
        s = a + b
        if s in shortcuts:
            for c, d in shortcuts[s]:
                print(a, b, c, d)
            continue
        shortcuts[s] = []
        if s + c_min + d_min > X or s + c_max + d_max < X:
            continue
        for c in C:
            d = X - a - b - c
            if d in ds:
                print(a, b, c, d)
                shortcuts[s].append((c, d))

We can have O(n^2) by hashing pair sums for A and B and checking if for any one of them, sum_AB[i] there might be an X - sum_AB[i] hashed in the pair sums of C and D. 对于A和B,我们可以通过哈希对和得到O(n^2) ,并检查对于它们中的任何一个, sum_AB[i]可能在C和D的对中可能存在X - sum_AB[i]哈希值。

In some circumstances it could be more efficient to enumerate those sums by multiplying each pair of lists as counts of coefficients in polynomials, using a FFT for O(m log m) complexity, where m is the range. 在某些情况下,通过将每对列表乘以多项式中的系数计数,使用FFT得到O(m log m)复杂度来枚举这些和可能更有效,其中m是范围。

a kind of dynamic programming approach. 一种动态编程方法。

initialize sums (a dict of the form {possible_sum0: [way_to_get_sum0, ...]} ) with the first list A . 使用第一个列表A初始化sums (形式{possible_sum0: [way_to_get_sum0, ...]}的形式的dict )。 this results in 这导致了

sums = {0: [[0]], 100: [[100]], -100: [[-100]], 50: [[50]], 200: [[200]]}

the update that dictionary with the lists B and C . 用列表BC更新该字典。 sums will now contain entries like sums现在将包含像

sums = {..., 
        30: [[0, 30, 0]], 
        50: [[0, 30, 20], [50, 0, 0]], 
        29: [[0, 30, -1]], ...}

then in find_sum i sort the last list D and the sums for some speedup and break if a give sum X is no longer accessible. 然后在find_sum我排序的最后名单Dsums对于一些加速和break ,如果一个给总和X不再访问。

here is the code: 这是代码:

from collections import defaultdict

A = [0, 100, -100, 50, 200]
B = [30, 100, 20, 0]
C = [0, 20, -1, 80]
D = [50, 0, -200, 1]

def initialize_sums(lst):
    return {item: [[item]] for item in lst}

def update_sums(sums, lst):
    new_sums = defaultdict(list)
    for sm, ways in sums.items():
        for item in lst:
            new_sum = sm + item
            for way in ways:
                new_sums[new_sum].append(way + [item])
    return new_sums

def find_sum(sums, last_lst, X):
    last_lst = sorted(last_lst)
    ret = []
    for sm, ways in sorted(sums.items()):
        for item in last_lst:
            x = sm + item
            if x > X:
                break
            if x == X:
                for way in ways:
                    ret.append(way + [item])
                break
    return ret


sums = initialize_sums(lst=A)
sums = update_sums(sums, lst=B)
sums = update_sums(sums, lst=C)

ret = find_sum(sums, last_lst=D, X=0)
print(ret)
# [[-100, 30, 20, 50], [0, 0, -1, 1], [-100, 100, -1, 1], ...]

...did not analyze the overall complexity though. ......虽然没有分析整体复杂性。

find all combinations for an array 找到数组的所有组合

def dOfSums(li):
  return {sum(x):x for x in sum([list(itertools.combinations(li, i)) for i in range(2,len(li))],[])}

find sums for a number in an array 查找数组中数字的总和

def findSums(li, num):
    return [((namestr(l), dOfSums(l)[num]) for l in li if num in dOfSums(l).keys() ]

name the array 命名数组

def namestr(obj):
    return [name for name in globals() if globals()[name] is obj].pop()

test 测试

for el in findSums([A,B,C,D],50):
    print(el)

('A', (0, 100, -100, 50))
('B', (30, 20, 0))
('D', (50, 0))

for el in findSums([A,B,C,D],100):
    print(el)

('A', (0, -100, 200))
('B', (100, 0))
('C', (0, 20, 80))

for el in findSums([A,B,C,D],0):
    print(el)

('A', (0, 100, -100))
A = [0, 100, -100, 50, 200]
B = [30, 100, 20, 0]
C = [0, 20, -1, 80]
D = [50, 0, -200, 1]

solutions = [(x1,x2,x3,x4) for x1 in A for x2 in B for x3 in C for x4 in D if sum([x1,x2,x3,x4]) == 0]
print(solutions)

Output: 输出:

>>>[(0, 0, 0, 0), (0, 0, -1, 1), (100, 100, 0, -200), (100, 20, 80, -200), (-100, 30, 20, 50), (-100, 100, 0, 0), (-100, 100, -1, 1), (-100, 20, 80, 0), (200, 0, 0, -200)]

This does exactly what you listed in your steps and works for any size, I don't know if it can get any easier finding all solutions for different list sizes. 这正是您在步骤中列出并适用于任何大小的内容,我不知道是否可以更轻松地找到针对不同列表大小的所有解决方案。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 给定一个由 N 个整数组成的数组和一个整数 K,找出该数组中总和等于 K 的元素对的数量 - Given an array of N integers, and an integer K, find the number of pairs of elements in the array whose sum is equal to K 给定一个数组; 我需要子阵列; 其元素的XOR值等于某个给定值 - Given an array; I need the sub-arrays; whose elements' XOR value is equal to some given value 如何打印列表的元素,其总和等于 python 中的给定数字? - how to print elements of a list whose sum is equal to a given number in python? 两个排序数组,两个元素之和等于一定数目 - Two Sorted Arrays, sum of 2 elements equal a certain number 列表中总和等于或小于给定数字的元素列表 - list of elements from a list that sum is equal or less than to a given number 给定一个数字,创建一个2元组,其总和等于从(1,1)开始的提供的数字 - Given a number, create a set of 2-tuples whose sum is equal to the provided number starting from (1, 1) 从给定值列表中查找固定长度子列表的最快方法,其值之和等于定义的数字 - Fastest way to find sub-lists of a fixed length, from a given list of values, whose elements sum equals a defined number 给定一个数组,找到总和等于给定总和的元素对,并返回其索引的总和 - Given an array find element pairs whose sum is equal to the given sum and return the sum of their indices select 来自 pandas 列的 n 个元素,其总和等于提供的数字 - select n elements from a pandas column whose sum is equal to a provided number 给定一个整数数组,从 1 到 X 找到总和为 N 的 K 个数字 - Given an array of integers, from 1 to X find K numbers that sum to N
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM