題目描述:
給定一個沒有排序的鏈表,去掉重復項,并保留原順序 如: 1->3->1->5->5->7,去掉重復項后變為:1->3->5->7
方法:
- 順序刪除
- 遞歸刪除
1.順序刪除
由于這種方法采用雙重循環對鏈表進行遍歷,因此,時間復雜度為O(n**2)
在遍歷鏈表的過程中,使用了常數個額外的指針變量來保存當前遍歷的結點,前驅結點和被刪除的結點,所以空間復雜度為O(1)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
|
#!/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)
由于遞歸法會增加許多額外的函數調用,所以從理論上講,該方法效率比方法一低
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
|
#!/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無序鏈表刪除重復項的方法,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對服務器之家網站的支持!
如果你覺得本文對你有幫助,歡迎轉載,煩請注明出處,謝謝!
原文鏈接:https://blog.csdn.net/weixin_44321080/article/details/103996333