刚进行面试测试,我必须在列表中找到第一个唯一(非重复)元素并将其返回。如果未找到唯一元素,则返回-1。我被告知我的解决方案不是最佳的。有人可以提出更好的方法吗?
这是我的代码:
def solution(lst):
if len(lst) == 1:
return lst[0]
elif lst == []:
return -1
for i in lst:
if lst.count(i) == 1:
return i
return -1
答案 0 :(得分:5)
def solution(it):
d = OrderedDict()
for x in it:
d[x] = d.get(x, 0) + 1
return next((x for x in d if d[x] == 1), -1)
示例:
>>> solution([1,2,1,3,2,5])
3
>>> solution([1,2,1,3,3,2,5])
5
>>> solution([1,2,1,3,3,2,5,5])
-1
更新:使用collections.Counter
def solution(seq):
d = Counter(seq)
return next((x for x in seq if d[x] == 1), -1)
答案 1 :(得分:4)
这可能是最有效的方法。它是O(n),因为它只是列表中的两次遍历。
只是fyi,你的解决方案显然是O(n ^ 2),这可能是你的面试官不喜欢它的原因。
# Fast O(n) solution using a dictionary
def solution(lst):
counts = {}
for item in lst:
if item in counts:
counts[item] += 1
else:
counts[item] = 1
for item in lst:
if counts[item] == 1:
return item
return -1
print(solution([1,2,1,3,2,5])) # prints 3
print(solution([1,2,1,3,3,2,5])) # prints 5
print(solution([1,2,1,3,3,2,5,5])) # prints -1
print(solution([7])) # prints 7
答案 2 :(得分:3)
我会把我的版本扔进戒指:
def solution(lst):
seen = set()
for i in lst:
if i in seen:
continue
if lst.count(i) == 1:
return i
else:
seen.add(i)
return -1
定时器:
import timeit
from collections import OrderedDict
test = [1,2,1,3,2,5]
def falsetru(l):
d = OrderedDict()
for x in l:
d[x] = d.get(x, 0) + 1
return next((x for x in d if d[x] == 1), -1)
def inbar(lst):
seen = set()
for i in lst:
if i in seen:
continue
if lst.count(i) == 1:
return i
else:
seen.add(i)
return -1
>>> print timeit.Timer('inbar(test)', 'from __main__ import *').repeat()
[1.4576762138175334, 1.4347494767197622, 1.4615902215846446]
>>> print timeit.Timer('falsetru(test)', 'from __main__ import *').repeat()
[26.38230001155711, 27.358966390824754, 29.19406918489357]
我对这些结果感到惊讶。
答案 3 :(得分:2)
在代码的最后部分:
for i in lst:
if lst.count(i) == 1:
return i
您在for循环的每次迭代中遍历列表。这导致O(n ^ 2),这是相当慢并且不是最佳的。
我建议用以下代码替换此部分:
lst.sort()
for i in range(len(lst)):
if i == 0:
if lst[i] != lst[i+1]: # if not same as next element
return lst[i] # okay, it's unique
if i == len(lst) - 1: # it's the last element
if lst[i-1] != lst[i]: # let's check if the previous element is the same
return lst[i] # okay, it's unique
if lst[i-1] != lst[i] and lst[i] != lst[i+1]: # let's check if the previous element and next element are both not equal to the current element
return lst[i] # okay, it's unique
排序算法在O(n log n)中完成,并且遍历列表的是O(n),因此它是O(n log n)。
编辑:发现Shashank Gupta已经在我面前发布了,所以这是另一个需要考虑的版本。答案 4 :(得分:0)
对你的采访感到抱歉。下一次,使用numpy
单线解决方案给他们留下深刻印象:
>>> a=array([1,2,1,3,2,5])
>>> a[sum(a==a.T[...,newaxis], axis=1)==1][0]
3
好的,不完全是单行。您需要使用try
except
来捕捉每个元素都不唯一的情况。