Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/284.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逻辑,防止在嵌套循环中比较数组时超时_Python_Arrays_Python 2.7 - Fatal编程技术网

更好的python逻辑,防止在嵌套循环中比较数组时超时

更好的python逻辑,防止在嵌套循环中比较数组时超时,python,arrays,python-2.7,Python,Arrays,Python 2.7,我试图解决一个编程难题,我编写的程序正确地解决了这个问题的小测试数据。但当他们在更大的数据集上运行时,我的程序在某些情况下超时。我主要是自学成才的程序员,如果有比我的逻辑更好的算法/实现,你们能告诉我吗。谢谢 问题 给定一个整数数组a,返回任意 一对数字,使得该对中较大的整数出现在 索引(在数组中)大于较小的整数返回-1如果需要 找不到满足此条件的对 我的Python函数 def maxDifference( a): diff=0 find=0 leng = len(a)

我试图解决一个编程难题,我编写的程序正确地解决了这个问题的小测试数据。但当他们在更大的数据集上运行时,我的程序在某些情况下超时。我主要是自学成才的程序员,如果有比我的逻辑更好的算法/实现,你们能告诉我吗。谢谢

问题

给定一个整数数组a,返回任意 一对数字,使得该对中较大的整数出现在 索引(在数组中)大于较小的整数<代码>返回-1如果需要 找不到满足此条件的对

我的Python函数

def maxDifference( a):
    diff=0
    find=0
    leng = len(a)
    for x in range(0,leng-1):
        for y in range(x+1,leng):
            if(a[y]-a[x]>=diff):
                  diff=a[y]-a[x]
                  find=1
    if find==1:
        return diff
    else:
        return -1
约束条件:

1 <= N <= 1,000,000
-1,000,000 <= a[i] <= 1,000,000 i belongs to [1,N]
Array { 2,3,10,2,4,8,1}
8
样本输出:

1 <= N <= 1,000,000
-1,000,000 <= a[i] <= 1,000,000 i belongs to [1,N]
Array { 2,3,10,2,4,8,1}
8

这是一个线性时间解。它跟踪列表中每个索引之前的最小值。这些最小值存储在列表中。最后,通过压缩原始列表和最小列表的对应元素,将它们之间的差异计算到另一个差异列表中。此差异列表中的最大值应为所需答案

def get_max_diff(lst):
    min_lst = []
    running_min = lst[0]
    for item in lst:
        if item < running_min:
            running_min = item
        min_lst.append(running_min)
    val = max(x-y for (x, y) in zip(lst, min_lst))
    if not val:
        return -1
    return val

>>> get_max_diff([5, 6, 2, 12, 8, 15])
13
>>> get_max_diff([2, 3, 10, 2, 4, 8, 1])
8
>>> get_max_diff([5, 4, 3, 2, 1])
-1
def get_max_diff(lst):
最小值=[]
正在运行的\u min=lst[0]
对于lst中的项目:
如果项目>>获取最大差异([5,6,2,12,8,15])
13
>>>获取最大差异([2,3,10,2,4,8,1])
8.
>>>获取最大差异([5,4,3,2,1])
-1

程序耗时过长的原因是嵌套循环本身就意味着二次时间

外循环通过
N-1
索引。内部循环每次通过不同数量的索引,但平均值明显向上取整。因此,通过内环的总次数为
(N-1)*(N-1)/2
,即
O(N^2)
。对于最大
N=1000000
,这意味着4999990001次迭代。那要花很长时间

诀窍是找到一种在线性时间内实现这一点的方法

这里有一个解决方案(作为一个模糊的描述,而不是实际的代码,所以当有人面临与您相同的测试时,他们不能复制并粘贴它):

  • 在每个索引之前列出最小值。每一个都是
    min(最小的_值[-1],arr[i])
    ,显然您可以通过
    N
    步骤来完成
  • 列出每个索引后的最大值。最简单的方法是反转列表,执行与上面完全相同的循环(但使用
    max
    而不是
    min
    ),然后再次反转。(当然,反转列表需要
    N
    步骤。)
  • 现在,对于列表中的每个元素,您只需与
    最小值[i]
    最大值[i]
    进行比较,而不是与其他每个元素进行比较。由于您只对每个
    N
    值进行两次比较,因此这需要
    2N
    时间
所以,即使是懒惰和幼稚的人,这也是总共的
N+3N+2N
步骤,也就是
O(N)
。如果
N=1000000
,这意味着6000000个步骤,比4999990001快了很多


显然,您可以看到如何删除这两个反转,以及如何跳过第一个和最后一个比较。如果你很聪明,你可以看到如何将整个
最大值
从等式中完全去掉。最后,我认为你可以把它归结为
2N-3步,或者1999997步。但这只是一个小小的持续改进;远没有解决基本算法问题那么重要。通过使用PyPy而不是CPython运行简单的代码,或者通过转换为NumPy,您可能会获得比3x(可能是20x)更大的改进,但除了更改算法之外,您不会以任何方式获得83333x的改进。

,我认为,由于有人在同一个问题上可以复制您的代码并使用它运行,我不会因为他们复制一些更优化的代码而失眠:

import time
import random

def max_difference1(a):
    # your function

def max_difference2(a):
    diff = 0

    for i in range(0, len(a)-1):
        curr_diff = max(a[i+1:]) - a[i]
        diff = max(curr_diff, diff)

    return diff if diff != 0 else -1

my_randoms = random.sample(range(100000), 1000)

t01 = time.time()
max_dif1 = max_difference1(my_randoms)
dt1 = time.time() - t01

t02 = time.time()
max_dif2 = max_difference2(my_randoms)
dt2 = time.time() - t02

print("The maximum difference is", max_dif1)
print("Time taken by your method:", dt1)
print("Time taken by my method:", dt2)
print("My method is", dt1/dt2, "times faster.")

The maximum difference is 99895
Time taken by your method: 0.5533690452575684
Time taken by my method: 0.08005285263061523
My method is 6.912546237558299 times faster.
与@abarnert所说的类似(我发誓,他总是在这些事情上挖苦我),你不想在列表上重复两次。你可以利用这样一个事实:你知道你的大价值必须在小价值之前。您还可以利用这样一个事实:除了最大的数字之外,您不关心任何事情,也就是说,在列表
[1,3,8,5,9]
中,最大的差异是8(9-1),您不关心其中是否有3、8和5。因此:
max(a[i+1:])-a[i]
是给定索引的最大差异

然后将其与
diff
进行比较,并将其中较大的一个与
max
进行比较,因为如果curr\u diff>diff:diff=curr\u diff
(或等效值),则调用默认内置python函数的速度略快于

return
行只是您在1行中的(固定)行,而不是4行



如您所见,在1000个示例中,此方法快了约6倍(注意:使用了Python3.4,但在Python2.x上不会出现任何问题)

那么。。。由于您只需要在最小的数字后面找到最大的数字,只要差异是目前为止最大的,就没有理由在数组的某个切片上进行多次传递或使用
max()

def f1(a):
    smallest = a[0]
    result = 0
    for b in a:
        if b < smallest: 
            smallest = b
        if b - smallest > result:
            result = b - smallest

    return result if result > 0 else -1

有嵌套的for循环,所以它是
O(n^2)
,这在任何在线判断中都不容易接受。这里有一个提示:你可以在线性时间内找到每个索引之前的最大值。可以在线性时间内找到每个索引后的最小值。一旦你有了这两个列表,你怎么能避免内环,使整个算法的时间是线性的而不是二次的?同时,你声称这段代码给出了正确的输出,除了针对一些大数据超时之外