![](/img/trans.png)
[英]What's the most efficient way to multiply between pandas dataframes over multiple factors?
[英]What's the most efficient way to find factors in a list?
我需要創建一個函數,給定一個正整數列表(可能有重復的整數),計算所有三元組(在列表中),其中第三個數字是第二個的倍數,第二個是第一個的倍數:
(相同的數字不能在一個三元組中使用兩次,但可以被所有其他三元組使用)
例如, [3, 6, 18]
是1,因為18
均勻分為6
,均勻分為3
。
所以給出[1, 2, 3, 4, 5, 6]
它應該找到:
[1, 2, 4] [1, 2, 6] [1, 3, 6]
並返回3
(找到的三元組數)
我做了一些有效的功能,但效率不高。 是否有一些我不知道的數學概念可以幫助我更快地找到這些三元組? 具有更好功能的模塊? 我不知道該搜索什么...
def foo(q):
l = sorted(q)
ln = range(len(l))
for x in ln:
if len(l[x:]) > 1:
for y in ln[x + 1:]:
if (len(l[y:]) > 0) and (l[y] % l[x] == 0):
for z in ln[y + 1:]:
if l[z] % l[y] == 0:
ans += 1
return ans
這個更快一點:
def bar(q):
l = sorted(q)
ans = 0
for x2, x in enumerate(l):
pool = l[x2 + 1:]
if len(pool) > 1:
for y2, y in enumerate(pool):
pool2 = pool[y2 + 1:]
if pool2 and (y % x == 0):
for z in pool2:
if z % y == 0:
ans += 1
return ans
這是我從你們所有人那里得到的幫助,但我必須做錯事,因為它得到了錯誤的答案(盡管它真的很快):
def function4(numbers):
ans = 0
num_dict = {}
index = 0
for x in numbers:
index += 1
num_dict[x] = [y for y in numbers[index:] if y % x == 0]
for x in numbers:
for y in num_dict[x]:
for z in num_dict[y]:
print(x, y, z)
ans += 1
return ans
( 39889
而不是40888
) - 哦,我不小心將索引var開始為1而不是0.它現在有效。
通過重新評估我需要它做什么,我找到了找到三元組數量的最佳方法。 這種方法實際上並沒有找到三元組,它只計算它們。
def foo(l):
llen = len(l)
total = 0
cache = {}
for i in range(llen):
cache[i] = 0
for x in range(llen):
for y in range(x + 1, llen):
if l[y] % l[x] == 0:
cache[y] += 1
total += cache[x]
return total
這里有一個函數版本可以解釋思考過程(雖然因為垃圾郵件打印而對大型列表不利):
def bar(l):
list_length = len(l)
total_triples = 0
cache = {}
for i in range(list_length):
cache[i] = 0
for x in range(list_length):
print("\n\nfor index[{}]: {}".format(x, l[x]))
for y in range(x + 1, list_length):
print("\n\ttry index[{}]: {}".format(y, l[y]))
if l[y] % l[x] == 0:
print("\n\t\t{} can be evenly diveded by {}".format(l[y], l[x]))
cache[y] += 1
total_triples += cache[x]
print("\t\tcache[{0}] is now {1}".format(y, cache[y]))
print("\t\tcount is now {}".format(total_triples))
print("\t\t(+{} from cache[{}])".format(cache[x], x))
else:
print("\n\t\tfalse")
print("\ntotal number of triples:", total_triples)
現在你的算法有O(N ^ 3)運行時間,這意味着每次你加倍初始列表的長度時,運行時間會增加8倍。
在最壞的情況下,你無法改善這一點。 例如,如果你的數字都是2的連續冪,意味着每個數字除以每個數字都比它更重要,那么每三個數字都是一個有效的解決方案,所以打印出來的所有解決方案都會像你現在在做什么
如果你有一個較低的“密度”數字來划分其他數字,你可以做的一件事就是搜索成對的數字而不是三元組。 這將花費時間僅為O(N ^ 2),這意味着當您將輸入列表的長度加倍時,運行時間會增加4倍。 一旦你有一對數字列表,你可以用它來建立一個三元組列表。
# For simplicity, I assume that a number can't occur more than once in the list.
# You will need to tweak this algorithm to be able to deal with duplicates.
# this dictionary will map each number `n` to the list of other numbers
# that appear on the list that are multiples of `n`.
multiples = {}
for n in numbers:
multiples[n] = []
# Going through each combination takes time O(N^2)
for x in numbers:
for y in numbers:
if x != y and y % x == 0:
multiples[x].append(y)
# The speed on this last step will depend on how many numbers
# are multiples of other numbers. In the worst case this will
# be just as slow as your current algoritm. In the fastest case
# (when no numbers divide other numbers) then it will be just a
# O(N) scan for the outermost loop.
for x in numbers:
for y in multiples[x]:
for z in multiples[y]:
print(x,y,z)
可能有更快的算法,也利用除法的代數屬性,但在你的情況下,我認為O(N ^ 2)可能足夠快。
關鍵的見解是:
如果一個分B時,它是指 “配合到B”。 如果a不除c ,則表示“ a不適合c ”。 而如果無法放入C,那么B無法放入C(想象若B安裝到C, 因為裝配到B, 然后將融入所有B的配合到C等一將不得不也適合c ..(想想主要因子化等))
這意味着我們可以優化。 如果我們將數字從最小到最大排序,首先從較小的數字開始。 第一次迭代中,開始用最小數作為如果我們的數字分成兩組,第1組,人數其中分頻和2組其中不分組,那么我們知道,在組沒有數字1罐分割數在2組,因為在第2組沒有數字具有作為一個因素。
所以,如果我們有[2,3,4,5,6,7],我們將從2開始並獲得:[2,4,6]和[3,5,7]我們可以在每個組重復該過程,分成小組。 這表明一種算法可以更有效地計算三元組。 這些組很快就會非常小,這意味着它的效率應該非常接近輸出的大小。
這是迄今為止我能夠提出的最佳答案。 它速度快,但速度不夠快。 我還在發帖,因為我可能會放棄這個問題,不想遺漏任何進展。
def answer(l):
num_dict = {}
ans_set = set()
for a2, a in enumerate(l):
num_dict[(a, a2)] = []
for x2, x in enumerate(l):
for y2, y in enumerate(l):
if (y, y2) != (x, x2) and y % x == 0:
pair = (y, y2)
num_dict[(x, x2)].append(pair)
for x in num_dict:
for y in num_dict[x]:
for z in num_dict[y]:
ans_set.add((x[0], y[0], z[0]))
return len(ans_set)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.