![](/img/trans.png)
[英]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
[英]From 4 given arrays(not sorted), find the elements from each array whose sum is equal to some number X
假設有4個未排序的數組,如下所示:
A = [0, 100, -100, 50, 200]
B = [30, 100, 20, 0]
C = [0, 20, -1, 80]
D = [50, 0, -200, 1]
假設X為0,那么可能的O / P應該是少數(從每個滿足條件的數組中選擇1個元素):
0,0,0,0
-100, 100, 0, 0
-100, 30, 20,50 .. etc.
我能夠設計出可以在O(n ^ 3LogN)中執行此操作的算法,有沒有更好的方法來實現相同的目標?
我的解決方案
1-排序每個陣列。
2-修復了陣列A中的元素。
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.)
有什么建議嗎?
假設你的數組都具有相同的長度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)
如果一個或多個數組包含(許多)極值,您還可以通過檢查后續數組的min
和max
的運行總和來查看快捷鍵,以查看是否仍然可以訪問X
例如:
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)
您可以通過存儲已經找到的運行總和(例如前兩個數組)的解決方案來進一步擴展這一點,並因此在再次遇到這樣的總和時采用快捷方式(通過使用最小/最大檢查重新排序可以避免重復計算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))
對於A和B,我們可以通過哈希對和得到O(n^2)
,並檢查對於它們中的任何一個, sum_AB[i]
可能在C和D的對中可能存在X - sum_AB[i]
哈希值。
在某些情況下,通過將每對列表乘以多項式中的系數計數,使用FFT得到O(m log m)
復雜度來枚舉這些和可能更有效,其中m
是范圍。
一種動態編程方法。
使用第一個列表A
初始化sums
(形式{possible_sum0: [way_to_get_sum0, ...]}
的形式的dict
)。 這導致了
sums = {0: [[0]], 100: [[100]], -100: [[-100]], 50: [[50]], 200: [[200]]}
用列表B
和C
更新該字典。 sums
現在將包含像
sums = {...,
30: [[0, 30, 0]],
50: [[0, 30, 20], [50, 0, 0]],
29: [[0, 30, -1]], ...}
然后在find_sum
我排序的最后名單D
和sums
對於一些加速和break
,如果一個給總和X
不再訪問。
這是代碼:
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], ...]
......雖然沒有分析整體復雜性。
找到數組的所有組合
def dOfSums(li):
return {sum(x):x for x in sum([list(itertools.combinations(li, i)) for i in range(2,len(li))],[])}
查找數組中數字的總和
def findSums(li, num):
return [((namestr(l), dOfSums(l)[num]) for l in li if num in dOfSums(l).keys() ]
命名數組
def namestr(obj):
return [name for name in globals() if globals()[name] is obj].pop()
測試
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)
輸出:
>>>[(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)]
這正是您在步驟中列出並適用於任何大小的內容,我不知道是否可以更輕松地找到針對不同列表大小的所有解決方案。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.