1. 程式人生 > 程式設計 >python無序連結串列刪除重複項的方法

python無序連結串列刪除重複項的方法

題目描述:

給定一個沒有排序的連結串列,去掉重複項,並保留原順序 如: 1->3->1->5->5->7,去掉重複項後變為:1->3->5->7

方法:

  1. 順序刪除
  2. 遞迴刪除

1.順序刪除

由於這種方法採用雙重迴圈對連結串列進行遍歷,因此,時間複雜度為O(n**2)
在遍歷連結串列的過程中,使用了常數個額外的指標變數來儲存當前遍歷的結點,前驅結點和被刪除的結點,所以空間複雜度為O(1)

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# @Time  : 2020/1/15 20:55
# @Author : buu
# @Software: PyCharm
# @Blog  :https://blog.csdn.net/weixin_44321080
class LNode:
  def __init__(self,x):
    self.data = x
    self.next = None

def removeDup(head):
  """
  對帶頭結點的無序單鏈表刪除重複的結點
  順序刪除:通過雙重迴圈直接在連結串列上進行刪除操作
  即,外層迴圈用一個指標從第一個結點開始遍歷整個連結串列,內層迴圈從外層指標指向的下一個結點開始,
  遍歷其餘結點,將與外層迴圈遍歷到的的指標所指的結點的資料域相同的結點刪除
  :param head: 頭指標
  :return:
  """
  if head is None or head.next is None:
    return
  outerCur = head.next
  innerCur = None
  innerPre = None
  while outerCur is not None:
    innerCur = outerCur.next
    innerPre = outerCur
    while innerCur is not None:
      if outerCur.data == innerCur.data:
        innerPre.next = innerCur.next
        innerCur = innerCur.next
      else:
        innerPre = innerCur
        innerCur = innerCur.next
    outerCur = outerCur.next

if __name__ == '__main__':
  i = 1
  head = LNode(6)
  tmp = None
  cur = head
  while i < 7:
    if i % 2 == 0:
      tmp = LNode(i + 1)
    elif i % 3 == 0:
      tmp = LNode(i - 2)
    else:
      tmp = LNode(i)
    cur.next = tmp
    cur = tmp
    i += 1
  print("before removeDup:")
  cur = head.next
  while cur is not None:
    print(cur.data,end=' ')
    cur = cur.next
  removeDup(head)
  print("\nafter removeDup:")
  cur = head.next
  while cur is not None:
    print(cur.data,end=' ')
    cur = cur.next

結果:

在這裡插入圖片描述

2.遞迴

此方法與方法一類似,從本質上而言,由於這種方法需要對連結串列進行雙重遍歷,所以時間複雜度為O(n**2)
由於遞迴法會增加許多額外的函式呼叫,所以從理論上講,該方法效率比方法一低

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# @Time  : 2020/1/15 21:30
# @Author : buu
# @Software: PyCharm
# @Blog  :https://blog.csdn.net/weixin_44321080
class LNode:
  def __init__(self,x):
    self.data = x
    self.next = None
def removeDupRecursion(head):
  """
  遞迴法:將問題逐步分解為小問題,即,對於結點cur,首先遞迴地刪除以cur.next為首
  的子連結串列中重複的結點;接著刪除以cur為首的連結串列中的重複結點,
  :param head:
  :return:
  """
  if head.next is None:
    return head
  pointer = None
  cur = head
  head.next = removeDupRecursion(head.next)
  pointer = head.next
  while pointer is not None:
    if head.data == pointer.data:
      cur.next = pointer.next
      pointer = cur.next
    else:
      pointer = pointer.next
      cur = cur.next
  return head
def removeDup(head):
  """
  對帶頭結點的單鏈表刪除重複結點
  :param head: 連結串列頭結點
  :return:
  """
  if head is None:
    return
  head.next = removeDupRecursion(head.next)
if __name__ == '__main__':
  i = 1
  head = LNode(6)
  tmp = None
  cur = head
  while i < 7:
    if i % 2 == 0:
      tmp = LNode(i + 1)
    elif i % 3 == 0:
      tmp = LNode(i - 2)
    else:
      tmp = LNode(i)
    cur.next = tmp
    cur = tmp
    i += 1
  print("before recursive removeDup:")
  cur = head.next
  while cur is not None:
    print(cur.data,end=' ')
    cur = cur.next
  removeDup(head)
  print("\nafter recurseve removeDup:")
  cur = head.next
  while cur is not None:
    print(cur.data,end=' ')
    cur = cur.next

結果:

在這裡插入圖片描述

引申:從有序連結串列中刪除重複項

上述介紹的方法也適用於連結串列有序的情況,但是由於上述方法沒有充分利用到連結串列有序這個條件,因此,演算法的效能肯定不是最優的。本題中,由於連結串列具有有序性,因此不需要對連結串列進行兩次遍歷。所以有如下思路:
用cur指向連結串列的第一個結點,此時需要分為以下兩種情況討論:

  • 如果cur.data == cur.next.data,則刪除cur.next結點;
  • 如果cur.data != cur.next.data,則cur=cur.next,繼續遍歷其餘結點;

總結

以上所述是小編給大家介紹的python無序連結串列刪除重複項的方法,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回覆大家的。在此也非常感謝大家對我們網站的支援!

如果你覺得本文對你有幫助,歡迎轉載,煩請註明出處,謝謝!