从数组中删除重复项并维护顺序 - O(n)时间并返回相同的引用

时间:2015-10-08 23:51:01

标签: python algorithm

['a', 'c','a','b','b'] -> ['a', 'c', 'b']

在线搜索没有帮助。我不确定这是否可能。

最好用Python编写解决方案,但一切都很好。

=====

编辑:我最初说O(1)空格,但我认为不可能。

更改要求:

没有空间要求,但您必须就地修改输入并将其返回。

7 个答案:

答案 0 :(得分:3)

这个怎么样?我认为时间复杂度和空间复杂度都是python3 my_parser2.py items-[0-9].xml items-[1-9][0-9].xml items-[1-9][0-9][0-9].xml

O(n)

答案 1 :(得分:2)

我不认为在O(n)时间 O(1)空间中这是可能的。要获得O(n)时间,你必须有一个暂存器(带有O(1)插入和查找,例如set)记录你已经看过的所有元素;这需要O(m)空间(其中m是唯一元素的数量)。相反,要获得O(1)空间,您必须为每个元素重新扫描数组中的早期元素,即O(n 2 )时间。

如果您接受O(m)暂存器,这将满足“在适当位置修改阵列”的要求并在O(n)时间内运行。

def remove_duplicates(arr):
    """Remove all duplicated elements from ARR in O(m) space and O(n) time.
       ARR is modified in place and is not returned (like `sort`)."""
    n = len(arr)
    if n <= 1: return
    seen = set((arr[0],))
    i = 1
    j = 1
    while i < n:
        if arr[i] not in seen:
           seen.add(arr[i])
           arr[j] = arr[i]
           j += 1
        i += 1
    del arr[j:i]

如果我在迭代它时从数组中删除了元素,那么这仍然是O(n 2 )时间,因为del arr[i]本身就是一个O(n)操作:它有在i之后滑动所有内容。 del arr[j:i]其中i超过数组的结尾应为O(1),但如果真的很重要,则必须check the implementation。< / p>

如果你必须有O(1)空格,这里是O(n 2 )时间算法:

def remove_duplicates_quadratic(arr):
    """Remove all duplicated elements from ARR in O(1) space and O(n²) time.
       ARR is modified in place and is not returned (like `sort`)."""
    n = len(arr)
    i = 0
    while i < n:
       for j in range(i):
           if arr[j] == arr[i]:
               del arr[i]
               n -= 1
               break
       else:
           i += 1

我正在进行手动数组索引,因为从使用任何常用for..in结构迭代的数组中删除元素是不安全的。你可以在第一个中使用for..in循环,但是你会丢失parallel structure,因此它的可读性会降低。

如果您之前没有看过,只有当循环 <\ n>通过break退出时才会执行an else clause on a loop

答案 2 :(得分:0)

from collections import OrderedDict

OrderedDict.fromkeys(my_array).keys()

答案 3 :(得分:0)

pip install oset

import oset

ll = oset.oset(['a', 'c','a','b','b'])

print(ll)

OrderedSet(['a', 'c', 'b'])`

答案 4 :(得分:0)

为了保持速度有效,您需要使用O(n)空间来记录已存在的记录。如果有大量重复,则不会占用太多空间。但是,标准数组上的del操作是O(n),因为它必须移动所有以下元素。

def uniquify(data):
    used = set()
    i = 0
    while i < len(data):
        if data[i] in used:
            del data[i] # or data.pop(i)
        else:
            used.add(data[i])
            i += 1
    return data # not strictly necessary because array is modified in-place

答案 5 :(得分:0)

O(n)时间,O(n)空间

uniqueList = []
index = 0
while index < len(myList):
    item = myList[index]
    if item not in uniqueList: uniqueList.append(item)
    else: myList.pop(index)
    index += 1

注意:请勿修改您正在迭代的列表,如下所示:

for index, item in enumerate(myListCopy):
    if item not in uniqueList: uniqueList.append(item)
    else: myList.pop(index)

O(n ^ 2)时间,O(1)空间 它肯定受到n ^ 2的限制,但实际上它更少。

index = 0
while index < len(myList):
    subIndex = index + 1
    while subIndex < len(myList):
        if myList[subIndex] == myList[index]: myList.pop(subIndex)
        subIndex += 1
    index += 1

O(n)时间,O(1)空间 如果您的列表已排序,并且您不介意删除第一个重复项。

for item in myList:
    if myList.count(item) > 1: myList.remove(item)

答案 6 :(得分:0)

lst1= ['a', 'c','a','b','b'] #-> ['a', 'c', 'b']
lst2 = []

for l in lst1:
   if l not in lst2:
       lst2.append(l)
 print lst2