我有两组数字,每组都在我的Python脚本的列表中。对于第一个列表中的每个数字,我需要查看第二个列表中的任何数字是否大于它。我只需要n2大于n1的次数。 (例如,如果numset1
为[7,2]
且numset2
为[6,9]
,我只需要3)
现在我正在这样做 - 通过每个n1并检查每个n2是否大于它:
possibilities = [(n1<n2) for n1 in numset1 for n2 in numset2]
numPossibilities = sum(possibilities)
目前这是我脚本中最慢的部分,特别是在处理较大的数据集时(numset1和numset2包含数千个数字)。我确信有一些方法可以提高效率,我只是不确定如何。
答案 0 :(得分:3)
排序numset2
,然后迭代numset1
,但在numset2
上使用二进制搜索,例如使用bisect模块:http://docs.python.org/2/library/bisect.html
import bisect
# your code here
numset2.sort()
L = len(numset2)
numPossibilities = sum([bisect.bisect_right(numset2,n1) < L for n1 in numset1])
另请注意,您的原始代码无法计算您在第二句中要求的内容 - 对于numset1
中的每个元素,它会在numset2
中总计多少元素大于这个元素,而不是是否有一个符合标准的元素。
要匹配原始代码,请执行以下操作:
numPossibilities = sum([L - bisect.bisect_right(numset2,n1) for n1 in numset1])
答案 1 :(得分:2)
您的问题是,您必须对(n1, n2)
的每个组合进行迭代,并且有len(numset1) * len(numset2)
个组合,当numset1
和numset2
仅公平时,这些组合会非常大大。
换句话说,算法的运行时间是O(n ^ 2)(如果len(numset1)
大约等于len(numset2)
。让我们的运行时间更快。: - )
如果我们对列表进行排序,这将变得更容易。我们要对numset1
和numset2
进行排序。
>>> numset1.sort()
>>> numset2.sort()
现在,比较numset1
的最小元素(称之为n1
)和numset2
的最小元素(称之为n2
)。如果n1
较小,则我们知道len(numset2)
中的numset2
元素大于n2
。如果numset1
较小,我们知道>>> n1_idx, n2_idx, accumulator = 0, 0, 0
>>> while n1_idx < len(numset1) and n2_idx < len(numset2):
if numset1[n1_idx] < numset2[n2_idx]:
accumulator += len(numset2) - n2_idx
n1_idx += 1
else:
n2_idx += 1
中的任何元素都不会小于它。
现在,我们不想实际删除列表开头的元素,因为这是对Python列表的O(n)操作。因此,让我们跟踪每个列表中的位置并进行迭代。
accumulator
在这个操作结束时,我们花了O(nlog(n))时间排序列表和O(n)时间进行迭代,所以我们的整体运行时复杂度是O(nlog(n))。 / p>
那个,而(n1, n2)
的{{1}}对的数量为n1 < n2
。
答案 2 :(得分:0)
这应该是一个非常有效的实现:
def get_possibilities(numset1, numset2):
sortset1 = sorted(numset1)
sortset2 = sorted(numset2)
total = 0
i2 = 0
for i1, n1 in enumerate(sortset1, 1):
while sortset2[i2] <= n1:
i2 += 1
if i2 >= len(sortset2):
# reached end of i2, so just return total now
return total
# current from sortset2 is greater than from sortset1 so far
total += i1
# all remaining elements of sortset2 greater than all elements of sortset1
total += (len(sortset2) - i2 - 1) * len(sortset1)
return total
这只迭代每个集合一次,它通过在运行之前对集合进行排序来完成。这允许一些改进的逻辑,因为如果索引sortset2
的{{1}}中的元素大于索引i2
的{{1}}元素,那么它也大于所有元素在早期指数的sortset1
中。