为什么我的python代码这么慢(leetcode)?

时间:2015-05-18 18:11:14

标签: python algorithm

  

给定一个整数数组,除了for之外,每个元素都会出现两次   一。找到那一个。

     

注意:       您的算法应具有线性运行时复杂性。你可以在不使用额外内存的情况下实现吗?

class Solution:
    # @param {integer[]} nums
    # @return {integer}
    def singleNumber(self, nums):
        prev = []
        for i,j in enumerate(nums):
            if j in prev:
                nums[i] = -j
            else:
                prev.append(j)
        return sum(nums)

这是来自leetcode的问题,实际上是AC率最高的问题。但是,正如我的代码所说,它告诉我时间限制已超出并且无法被接受。任何人都可以分析我的代码,包括复杂性吗?非常感谢。

Upadate: 谢谢大家,我已将“prev”从列表更改为一组,这很好用!

class Solution:
    # @param {integer[]} nums
    # @return {integer}
    def singleNumber(self, nums):
        prev = set([])
        for i,j in enumerate(nums):
            if j in prev:
                nums[i] = -j
            else:
                prev.add(j)
        return sum(nums)

然而,正如问题所描述的那样,我仍在寻找不需要额外记忆的解决方案。

更新: 我用另一种方法试图解决问题,但再次收到超过时间。

class Solution:
    # @param {integer[]} nums
    # @return {integer}
    def singleNumber(self, nums):
        for i,j in enumerate(nums):
            if j in set(nums[:i+1]):
                nums[i] = -j
        return sum(nums)

实际上我有点困惑,像nums [:i + 1]这样的切片会在每个循环中创建一个单独的列表吗?那么创建列表最耗时吗?我使用set而不是list,这样可以降低搜索成本。

4 个答案:

答案 0 :(得分:5)

@彼得的答案很棒:

def singleNumber(nums):
    unique = 0
    for num in nums:
        unique ^= num
    return unique

答案 1 :(得分:3)

Xor是要走的路。 两个相似元素的Xor为0,因此所有重复都将消失,导致res中存在非重复元素。

x=[1,1,2,3,2,4,4,5,5]
res=x[0]
for i in xrange(1,len(x)):
    res^=x[i]

print res

答案 2 :(得分:3)

这是编写XOR解决方案的另一种功能性方法。

from operator import xor

def single_number(nums):
    return reduce(xor, nums)

在Python 3.x中,(显然Leetcode不使用),您需要从reduce模块导入functools函数。

答案 3 :(得分:0)

你可以使用cython(我现在第二次使用它,所以可能还有改进):

使用以下内容创建文件singleNumber.pyx

def singleNumber(list nums, int nn):
cdef int i, ii, np
cdef list prev = []

for i in xrange(nn):
    np = len(prev)
    for ii in xrange(np):
        if nums[i] == prev[ii]:
            nums[i] = - prev[ii]
        else:
            prev.append(nums[i])
return sum(nums)

使用以下内容创建文件setup.py

from distutils.core import setup
from Cython.Build import cythonize

setup(
    ext_modules=cythonize('singleNumber.pyx'),
)

编译:{{1​​}}

python setup.py build_ext --inplace

结果:import singleNumber as sn arr = [i + 1 for i in range(1000)] %timeit sn.singleNumber(arr,len(arr))

使用100000 loops, best of 3: 15.4 µs per loop函数可以给我:XOR

编辑:

如果我使用10000 loops, best of 3: 82.1 µs per loop解决方案与原始函数相比,我会得到不同的结果!

XOR

给我:from operator import xor def singleNumber_xor(nums): return reduce(xor, nums) arr = [i + 1 for i in range(10000)] singleNumber_xor(arr)

原始功能:

10000

给我:def singleNumber_orig(nums): prev = set([]) for i,j in enumerate(nums): if j in prev: nums[i] = -j else: prev.add(j) return sum(nums) singleNumber_orig(arr)