从Python列表中删除重复项的更好解决方案
我有两个从列表中删除重复项的函数:从Python列表中删除重复项的更好解决方案,python,time-complexity,Python,Time Complexity,我有两个从列表中删除重复项的函数: def solution1(a: List): seen = set() result = [] for item in a: if item not in seen: seen.add(item) result.append(item) return result def solution2(a: List): result = [] for i
def solution1(a: List):
seen = set()
result = []
for item in a:
if item not in seen:
seen.add(item)
result.append(item)
return result
def solution2(a: List):
result = []
for item in a:
if item not in result:
result.append(item)
return result
我从中获得了解决方案1
。它的时间和空间复杂性是O(n)
我相信solution2
的空间复杂度也是O(n)
。时间复杂度是多少?的循环是O(n)
,但我不确定中的语句,因为结果的长度
没有输入a
大。它是否也只是O(n)
最后,如果两种解决方案具有相同的时间和空间复杂性,是否认为“更好”?在面试中我应该使用哪一种
看起来solution1
使用了更多的空间(可能O(2n)
但我知道我们应该去掉前面的常数),并且在更短的时间内完成(测试集合成员资格比测试列表成员资格更快)。我同意solution1
空间复杂性是O(2n)
但它可以近似为O(n)
,这在空间上与solution2
大致相同
然而,就时间效率而言,solution1
应该优于solution2
,因为set
数据结构(如果项不在可见状态:
)的查找时间大约是O(1)
,而常规python列表(如果项不在结果中:
)的查找时间是O(n)
。因此,在面试中使用解决方案1
会更好
有关Python数据结构的时间复杂性的更多信息,请参见此处
我同意解决方案1
空间复杂度是O(2n)
,但它可以近似为O(n)
,这在空间上与解决方案2
大致相同
然而,就时间效率而言,solution1
应该优于solution2
,因为set
数据结构(如果项不在可见状态:
)的查找时间大约是O(1)
,而常规python列表(如果项不在结果中:
)的查找时间是O(n)
。因此,在面试中使用解决方案1
会更好
有关Python数据结构的时间复杂性的更多信息,请参见此处
第二个答案实际上大于O(n)-它更像O(n^2)。这是因为如果项目不在结果中
的时间复杂度取决于列表结果
中元素的数量,即它是O(n)
。有关解释,请参阅此答案:
这就是为什么第一个答案更好的原因:它使用一个集合或字典,其时间复杂度(充其量)是常数时间。第二个答案实际上大于O(n)-它更像O(n^2)。这是因为如果项目不在结果中
的时间复杂度取决于列表结果
中元素的数量,即它是O(n)
。有关解释,请参阅此答案:
这就是为什么第一个答案更好的原因:它使用集合
或字典
,其时间复杂度(最多)是恒定时间。使用集合删除重复项
这里有一种方法:
dups = [10,20,30,40,50,10,20,50,60,80,90]
print (dups)
remove_dups = list(set(dups))
print(remove_dups)
输出如下所示:
原始清单:
[10, 20, 30, 40, 50, 10, 20, 50, 60, 80, 90]
已删除DUP列表:
[40, 10, 80, 50, 20, 90, 60, 30]
使用最小回望删除DUP
我还认为,这可能会减少查找,并且在保持顺序的同时比完整扫描列表更快
[a for i,a in enumerate (x) if a not in x[:i]]
结果如下:
[10, 20, 30, 40, 50, 60, 80, 90]
使用set删除重复项
这里有一种方法:
dups = [10,20,30,40,50,10,20,50,60,80,90]
print (dups)
remove_dups = list(set(dups))
print(remove_dups)
输出如下所示:
原始清单:
[10, 20, 30, 40, 50, 10, 20, 50, 60, 80, 90]
已删除DUP列表:
[40, 10, 80, 50, 20, 90, 60, 30]
使用最小回望删除DUP
我还认为,这可能会减少查找,并且在保持顺序的同时比完整扫描列表更快
[a for i,a in enumerate (x) if a not in x[:i]]
结果如下:
[10, 20, 30, 40, 50, 60, 80, 90]
考虑输入列表都是唯一的情况。毫无疑问,在这种情况下,解决方案2将是O(n^2);你在混淆视听。平均计算次数可以表示为2n,但渐近分析只表示为变量:O(n),O(n^2),O(lgn)。为什么不把列表转换成一个集合,然后再转换成一个列表呢。它将删除重复项。即使result
小于a
,在result
中的查找仍然随着n
线性增长,因此solution2
作为一个整体是O(n^2)。如果您想要最快的解决方案并表明您了解如何利用Python的优势:result=list(set(a))
是您所需要的全部(假设您不关心顺序)-否则,solution1
就可以了。O(2N)
就是O(N)
。在任何情况下,第二个解是二次时间,第一个解是线性时间。通常,基于集合的解决方案是考虑输入列表都是唯一的情况的方法。毫无疑问,在这种情况下,解决方案2将是O(n^2);你在混淆视听。平均计算次数可以表示为2n,但渐近分析只表示为变量:O(n),O(n^2),O(lgn)。为什么不把列表转换成一个集合,然后再转换成一个列表呢。它将删除重复项。即使result
小于a
,在result
中的查找仍然随着n
线性增长,因此solution2
作为一个整体是O(n^2)。如果您想要最快的解决方案并表明您了解如何利用Python的优势:result=list(set(a))
是您所需要的全部(假设您不关心顺序)-否则,solution1
就可以了。O(2N)
就是O(N)
。在任何情况下,第二个解是二次时间,第一个解是线性时间。通常,基于集合的解决方案是goAs‘m’与‘n’线性增长的方式,“O(nm)”只是一种令人困惑的方式