【问题标题】:Why is my program faster than the one using a python built in function?为什么我的程序比使用 python 内置函数的程序快?
【发布时间】:2015-07-09 03:56:12
【问题描述】:

好吧,我在 coderbyte 上做一个拼图,下面是拼图的内容:

让函数 SimpleMode(arr) 获取存储在 arr 中的数字数组并返回出现频率最高的数字(模式)。例如:如果 arr 包含 [10, 4, 5, 2, 4],则输出应为 4。如果有多个模式,则返回数组中第一个出现的模式(即 [5, 10, 10, 6 , 5] 应该返回 5,因为它首先出现)。如果没有模式返回-1。数组不会为空。

这是我的程序:

import time
from random import randrange

def SimpleMode(arr): 
  bestMode=0
  numTimes=0
  for x in range(len(arr)):
    if len(arr)>0:
      currentNum=arr[0]
      currentMode=0
      while currentNum in arr:
        currentMode+=1
        arr.remove(currentNum)
      if currentMode>numTimes:
        numTimes=currentMode
        bestMode=currentNum
    else: break
  if numTimes==1: bestMode=-1
  return bestMode

start_time = time.time()
numbers = [randrange(1,10) for x in range(0, 1000)]
print(SimpleMode(numbers))
print("--- %s seconds ---" % (time.time() - start_time))

这是别人写的一个更简单的程序:

import time
from random import randrange

def SimpleMode(arr): 

  best = -1
  best_count = 1

  for c in arr:
    if arr.count(c) > best_count:
      best = c
      best_count = arr.count(c)

  return best

start_time = time.time()
numbers = [randrange(1,10) for x in range(0, 1000)]
print(SimpleMode(numbers))
print("--- %s seconds ---" % (time.time() - start_time))

现在我知道使用我的计时方法取决于我的 CPU 正在做什么以及其他什么,所以这不是最准确的方法,但抛开这一点,我发现我的计算机需要 0.012000 秒来运行我的程序,但运行第二个程序需要 0.025001 秒。

现在我感到困惑。我自己编写的程序花费的时间不到其他程序的一半,该程序使用内置的 python 函数并且只有一个 for 循环,而我的程序在 for 循环中有一个 while 循环。

谁能提供对此的任何见解?

【问题讨论】:

  • 使用内置函数并不意味着使用更差的算法会更快。
  • 作为第一个猜测,您的循环需要较少的迭代,因为您删除了已经计算过的元素,因此 len(arr) > 0 在您遍历整个数组之前可能会为真。第二种算法无论如何都会遍历整个数组,因此根据数组的不同,一种算法可以击败另一种算法。你试过像[1, 2, 3, 4, 5, 6, ...]这样的数组吗?
  • @Amber 我在哪里可以找到 count() 使用的算法?
  • @Evert 是的,我使用的原始列表是 numbers = [x for x in range(0, 1000)] 结果是一样的。

标签: python list time


【解决方案1】:

第二个程序每次迭代调用count 两次,因为count 是 O(n)(也就是说,它必须遍历整个数组,就像 for 循环一样),时间很快加起来.

也就是说,您的程序可以进一步减少:

import collections

def SimpleMode(arr):
    if not arr:
        return -1
    counts = collections.Counter(arr)
    return max(counts, key=lambda k: (counts[k], -arr.index(k)))

此外,请注意,您的初始程序会改变其输入(由于.remove 调用,它有效地破坏了您传递给它的列表,如果您想在调用SimpleMode 后对arr 做任何事情,这将很糟糕) .

最后,在 Python 中,[1, 2, 3, 4] 结构称为列表,而不是数组。 Python 中有一个叫做数组的东西,它不是 this(大多数时候它是一个 NumPy 数组,但它也可以是来自 stdlib 中 array 模块的数组)。 p>

【讨论】:

  • 哦,我明白了。他本可以在 for 循环中计算一次 count(c),将其设置为变量,然后使用该变量。谢谢!也不确定 lambda 是如何工作的,但我会研究一下。
  • Lambda 只是匿名函数。我的程序的诀窍在于maxkey 参数如何工作(与sort 相同——查看docs.python.org/2/library/stdtypes.html#mutable-sequence-types
  • 是的,我知道它被称为列表,只是coderbyte.com 提供了六种不同语言的挑战,并且在大多数语言中它被称为数组。虽然它可能对其他人有帮助。
【解决方案2】:

您的代码一次性完成所有操作。
其他代码在arr.count() 中包含隐藏的嵌套循环。

【讨论】:

  • 在我看来,OP 的代码还包括 currentNum in arrarr.remove() 中的隐藏循环,但 arr.remove() 每次都使列表缩短约 100 个项目,这可能是效果更好。
猜你喜欢
  • 2018-01-02
  • 1970-01-01
  • 1970-01-01
  • 2018-05-23
  • 2018-01-21
  • 2016-02-13
  • 1970-01-01
  • 1970-01-01
  • 2013-08-24
相关资源
最近更新 更多