[英]The fastest way to find 2 numbers from two lists that in sum equal to x
我的代碼:
n = 3
a1 = 0
b1 = 10
a2 = 2
b2 = 2
if b1>n:
b1=n
if b2>n:
b2=n
diap1 = [x for x in range(a1, b1+1)]
diap2 = [x for x in range(a2, b2+1)]
def pairs(d1, d2, n):
res = 0
same = 0
sl1 = sorted(d1)
sl2 = sorted(d2)
for i in sl1:
for j in sl2:
if i+j==n and i!=j:
res+=1
elif i+j==n and i==j:
same+=1
return(res+same)
result = pairs(diap1, diap2, n)
print(result)
注意: n,a1,b1,a2,b2 可以改變 。 代碼應該從2個列表中找到2個數字(每個1個),總和等於n。 例如:對(a,b)和(b,a) 不同,但(a,a)和(a,a) 是同一對 。 因此,我的代碼輸出是正確的,對於上面的代碼是1(1,2),但對於大輸入,它需要太多時間。 如何優化它以更快地工作?
使用set()進行快速查找...
setd2 = set(d2)
不要嘗試所有可能的數字對。 一旦你修復了第一個列表中的數字,比如i,只要看看(ni)是否在第二個集合中。
for i in sl1:
if (n-i) in setd2:
# found match
else:
# no match in setd2 for i
通過以下方式,您可以最快地工作並找到總和等於n的兩個數字,並將它們存儲在元組列表中。
s1 = set(list1)
s2 = set(list2)
nums = []
for item in s1:
if n-item in s2:
nums.append((item, n-item))
感謝您明確定義問題並提供您嘗試優化的代碼示例。
利用您問題中的兩個關鍵定義和您提供的符號,我將優化嘗試限制為使用列表,並添加了隨機更改與n,a1,b1,a2和b2關聯的值的功能。
為了顯示優化結果,我創建了一個模塊,其中包括使用random.randit函數創建各種列表大小和timeit.Timer函數來捕獲原始pair()函數所需的時間量正如我在pairs2()函數中建議的優化。
在pairs2()函數中,您將注意到每個迭代循環都包含一個break語句。 一旦滿足所需的標准,這些就消除了對每個列表的不必要的迭代。 您應該注意,隨着列表大小的增加,pairs2()與pairs()時間會有所改善。
測試模塊代碼:
import random
from timeit import Timer
max_value = 10000
n = random.randint(1, max_value)
a1 = random.randint(0, max_value)
b1 = random.randint(1, max_value+1)
a2 = random.randint(0, max_value)
b2 = random.randint(1, max_value+1)
if b1>n:
b1=n
if b2>n:
b2=n
if a1>=b1:
a1 = random.randint(0, b1-1)
if a2>=b2:
a2 = random.randint(0, b2-1)
diap1 = [x for x in range(a1, b1)]
diap2 = [x for x in range(a2, b2)]
print("Length diap1 =", len(diap1))
print("Length diap2 =", len(diap2))
def pairs(d1, d2, n):
res = 0
same = 0
sl1 = sorted(d1)
sl2 = sorted(d2)
for i in sl1:
for j in sl2:
if i+j==n and i!=j:
res+=1
elif i+j==n and i==j:
same+=1
return(res+same)
def pairs2(d1, d2, n):
res = 0
same = 0
sl1 = sorted(d1)
sl2 = sorted(d2)
for i in sl1:
for j in sl2:
if i+j==n and i!=j:
res+=1
break
elif i+j==n and i==j:
same+=1
break
if res+same>0:
break
return(res+same)
if __name__ == "__main__":
result=0
timer = Timer("result = pairs(diap1, diap2, n)",
"from __main__ import diap1, diap2, n, pairs")
print("pairs_time = ", timer.timeit(number=1), "result =", result)
result=0
timer = Timer("result = pairs2(diap1, diap2, n)",
"from __main__ import diap1, diap2, n, pairs2")
print("pairs2_time = ", timer.timeit(number=1), "result =", result)
如果從第一個列表中提取值n,然后在第二個列表中搜索值m以使總和與搜索到的值匹配,則可以創建一些快捷方式。 例如,如果總和較小,則第二個列表中小於或等於m的所有值也不會給出正確的總和。 同樣,如果總和更大。
使用此信息,我將使用以下步驟:
請注意,使用堆是對兩個序列進行分類排序的優化。 但是,如果您經常遇到無匹配的情況,則在算法之前對數字進行排序可能是一種更快的方法。 這樣做的原因是一個好的排序算法將勝過通過堆的隱式排序,而不是通過其漸近復雜性而是通過一些常數因子。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.