关于代码战的说明:
有一个包含一些数字的数组。除了一个数字之外,所有的数字都是相等的。试着找到它!
find_uniq([1,1,1,2,1,1])== 2 find_uniq([0,0,0.55,0,0])== 0.55保证数组至少包含3个数字。
测试包含一些非常大的数组,因此要考虑性能。
这是我写的代码:
def find_uniq(arr):
for n in arr:
if arr.count(n) == 1:
return n
exit()
其工作原理如下:对于数组中的每个字符,如果该字符只出现一次,则返回该字符并退出代码;如果该字符出现多次,则不执行任何操作在codewars上尝试代码时,我得到以下错误:
STDERR执行超时(12000毫秒)
我是一个初学者,所以我不知道如何进一步优化代码,以便它不超时
我的代码的第一个版本看起来像这样:
def find_uniq(arr):
arr.sort()
rep = str(arr)
for character in arr:
cantidad = arr.count(character)
if cantidad > 1:
rep = rep.replace(str(character), "")
rep = rep.replace("[", "")
rep = rep.replace("]", "")
rep = rep.replace(",", "")
rep = rep.replace(" ", "")
rep = float(rep)
n = rep
return n
在超时之后,我认为这是由于重复的替换函数,以及代码必须遍历每个元素(即使已经找到正确的元素)的事实,因为代码删除了不正确的元素,而不仅仅是返回正确的元素
经过一些我没有保存的迭代之后,我们得到了当前代码,它检查字符是否在数组中只有一次,返回并退出
def find_uniq(arr):
for n in arr:
if arr.count(n) == 1:
return n
exit()
我不知道如何进一步优化它
4条答案
按热度按时间f2uvfpb91#
你可以使用
dict
或collections.Counter
来得到每个元素的频率,其时间复杂度为线性,然后返回频率为1的元素。zengzsys2#
每次调用
.count()
时,它都会遍历整个数组。如果您的数组包含n
元素,它将遍历数组n
次,这是相当慢的。您可以按照Unmitigate的建议使用
collections.Counter
,但是如果您不熟悉该模块,那么对于这个问题来说,它似乎有些过头了,因为在本例中您知道数组中只有两个唯一元素,所以可以使用set()
获得所有唯一元素,然后检查每个唯一元素的频率:wwtsj6pe3#
比较前两个数字。如果它们匹配,则查找数组中不匹配的数字(最长解)。否则,返回与第三个数字不匹配的数字。编码为:
wqnecbli4#
在原始代码中:
对数组中的每个元素调用一次
arr.count
(假设最坏的情况是唯一元素在最末尾),每次调用arr.count(n)
都会扫描整个数组,从n
开始计数--所以要对整个N个元素的数组迭代N次,这就是O(N^2)--如果N很大的话会非常慢!第二个版本的代码也有同样的问题,但是它将列表转换为字符串,然后尝试解析该字符串,从而增加了大量额外的复杂性--不要这样做!
加快速度的方法是迭代整个列表 * 一次 *,并跟踪每一项的计数,使用内置的
collections.Counter
类最容易做到这一点:如果数组中只有两个不同的值,并且其中一个值是唯一的,那么您可以通过将其分为两种可能性来提高效率(在所有情况下,您甚至不需要迭代整个数组):要么前两项是相同的,你只需要找到不等于它们的项,要么它们是不同的,你只需要返回不等于第三项的项.
在这种方法中,您只需要迭代数组中的唯一项(或者在它是前两个项之一的情况下正好超过它一个项).在唯一项接近一个非常长的数组的开始的特定情况下,这将比无论如何都迭代整个数组的方法快得多.在最坏的情况下,你仍然只有一次迭代。