Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/302.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 从两个总和等于x的列表中查找2个数字的最快方法_Python_Algorithm_Python 3.x - Fatal编程技术网

Python 从两个总和等于x的列表中查找2个数字的最快方法

Python 从两个总和等于x的列表中查找2个数字的最快方法,python,algorithm,python-3.x,Python,Algorithm,Python 3.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)

我的代码:

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个列表(每个列表1个)中找到2个总数等于n的数字。例如:对(a,b)和(b,a)不同,但(a,a)和(a,a)是同一对。所以,我的代码的输出是正确的,对于上面的代码,它是1(1,2),但是对于大的输入,它需要太多的时间。如何优化它以更快地工作?

使用set()进行快速查找

setd2 = set(d2)
不要尝试所有可能的数字对。一旦你确定了第一个列表中的一个数字,比如说i,就看看(n-i)是否在第二个列表中

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))

被接受的答案确实很容易理解和实现,但我不得不分享这个方法。您可以看到您的问题与此相同。
这尤其有趣,因为插入到集合中不需要额外的空间。我的答案中包括了算法

如果数组已排序,则可以在线性时间和恒定存储中进行排序

  • 从两个指针开始,一个指向A的最小元素,另一个指向B的最大元素
  • 计算指向的元素的总和
  • 如果小于k,则将指针增加到A中,使其指向下一个最大的元素
  • 如果大于k,则将指针减为B,使其指向下一个最小的元素
  • 如果正好是k,你就找到了一对。移动其中一个指针,继续寻找下一对指针

如果数组最初未排序,则可以首先对其排序,然后使用上述算法。

如果从第一个列表中提取值n,然后在第二个列表中搜索值m,以便总和与搜索值匹配,则可以进行一些快捷操作。例如,如果总和较小,则第二个列表中小于或等于m的所有值也不会给出正确的总和。同样,如果总和更大

使用此信息,我将使用以下步骤:

  • 设置两个堆,一个最小堆,一个最大堆
  • 查看每个堆的顶部元素:
    • 如果总和与搜索的值匹配,则完成
    • 如果总和超过搜索的值,请从最大堆中删除该值
    • 如果总和小于搜索的值,则从最小堆中删除该值
  • 如果任一堆为空,则没有解决方案

请注意,使用堆是对这两个序列立即排序的优化。但是,如果经常出现不匹配的情况,则在算法之前对数字进行排序可能是一种更快的方法。原因是一个好的排序算法将优于通过堆进行的隐式排序,不是因为它的渐进复杂性,而是因为一些常量因素。

感谢您清楚地定义了您的问题并提供了您的代码 您正在尝试优化的示例

利用问题中的两个关键定义和您需要的符号 但是,我将我的优化尝试限制为使用列表,并添加了 随机更改与n、a1、b1、a2和 b2

为了显示优化结果,我创建了一个模块,其中包括 使用random.randit函数创建各种列表大小和 timeit.Timer函数捕获原始pairs()函数所用的时间量,以及我在pairs2()函数中建议的优化

在pairs2()函数中,您将注意到每个迭代循环都包含一个 中断语句。这些方法消除了对每个列表进行一次不必要的迭代 达到了预期的标准。您应该注意,随着列表的大小 随着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)

您正在循环中计算相同的
,但没有返回。你真的需要这个值吗?@PiMarillion yes例如在输入DIP1=[1,2,3,4],DIP2=[1,2,3,4]和n=4时,它应该只计算一次对(2,2)。如果你的代码有效,提交它。如果用户想要两个不同的元素,这将不起作用。@adwaitkumar如果用户想要一辆法拉利,这也不起作用。;-)我的解决方案无法解决无限多的情况。事实上,我只是在暗示这个问题。。。您可能已经注意到我的代码实际上并没有运行。这样做的目的是为提问者指明正确的方向,让他们随波逐流。如果您需要不同的元素,我相信您足够聪明,可以修改您的程序来做到这一点。