阅读目录
题目描述
在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5
思路和Python实现
三枚指针 完成
-
新建一个头结点,以防第一个结点被删除。
-
保存当前结点的上个结点pre,当前结点pHead和它的下个结点pHead.next一起移动,循环遍历整个链表;如果当前结点的值与下一个结点的值相等时,先取一个中间值tmp保存当前值,然后让当前结点pHead开始向后移动,一直比较下一个值是否等于tmp,直到不等于,当前结点pHead到达一个位置,让上一个结点的pre指向pHead(等于还是在当前结点的上一个结点);继续判断pHead和下一个结点pHead.next值是否相等,如果相等,重复上述步骤,直到pHead.next指向None时,退出循环,让new_head.next指向移动后的pHead。
如果当前节点与next节点不相等,则直接将结点指针全部向后移动一位。(下图中,在pHead=2时,发现与下一结点相等,pHead移到了“5结点”,与下一结点也相等,但是pHead.next=None,不满足循环,直接就返回了头结点“1结点”)
class ListNode:
def __init__(self, x):
self.val = x
self.next = None
class Solution:
def deleteDuplication(self, pHead):
new_head = ListNode(None)
new_head.next = pHead # pHead 作为当前节点
pre = new_head # 当前节点的上一个节点
while pHead and pHead.next:
if pHead.val == pHead.next.val:
tmp = pHead.val
while pHead and pHead.val == tmp:
pHead = pHead.next
pre.next = pHead
else:
pre = pHead
pHead = pHead.next
return new_head.next
def print_list(self, node): # 打印测试
if node is None:
return None
while node:
print(node.val, end="")
node = node.next
print()
if __name__ == '__main__':
n1 = ListNode(2) # 依次实例5个结点
n2 = ListNode(2)
n3 = ListNode(3)
n4 = ListNode(5)
n5 = ListNode(6)
n1.next = n2 # 依次将结点链接起来,形成一个链表
n2.next = n3
n3.next = n4
n4.next = n5
obj = Solution()
obj.print_list(obj.deleteDuplication(n1)) # 3 5 6
通俗易懂的 四枚指针完成
- 为防止上来头结点就和第一个结点相同被删除,手动增加虚拟首结点
- anchor 指针:标志链接位置,初始化为虚拟首结点,最后输出整张新链表
- pre 指针:当前结点的直接前驱,初始化为虚拟首结点
- cur 指针:当前结点,初始化为头结点
- latter 指针:标志待判断结点的直接后继,初始化为结点点后继
- 根据题意,只有某结点与其直接前驱和直接后继都不相同时,才保留;latter到链表结尾,或者整个链表为空时退出
# -*- coding:utf-8 -*-
class ListNode:
def __init__(self, x):
self.val = x
self.next = None
class Solution:
def deleteDuplication(self, pHead):
if not pHead: # 如果链表为空
return None
new_head = ListNode(None) # 虚拟首结点
new_head.next = pHead # 指向头结点
anchor, pre, cur, latter = new_head, new_head, pHead, pHead.next # 初始化
while latter: # 让尾指针不断的向后移动
# 如果结点为一个不重复的结点,接到要返回的链上
if pre.val != cur.val and cur.val != latter.val:
anchor.next = cur
anchor = anchor.next
pre, cur, latter = cur, latter, latter.next # 指针向后移动
if pre.val == cur.val: # 最后一个结点,如果重复就不要,否则要
anchor.next = None
else:
anchor.next = cur
return new_head.next # 去掉虚拟首结点,返回
def print_list(self, node): # 打印测试
if node is None:
return None
while node:
print(node.val, end="")
node = node.next
print()
if __name__ == '__main__':
n1 = ListNode(2) # 依次实例5个结点
n2 = ListNode(3)
n3 = ListNode(3)
n4 = ListNode(5)
n5 = ListNode(6)
n1.next = n2 # 依次将结点链接起来,形成一个链表
n2.next = n3
n3.next = n4
n4.next = n5
obj = Solution()
obj.print_list(obj.deleteDuplication(n1)) # 2 5 6
递归实现
- 分成两种情况的子问题:第一种,第一个结点和第二个结点相等,第二个结点和后面的结点当作一个整体的子问题处理;第二种,第一个结点和第二个结点不相等,第一个结点移动到下一个结点,判断与当前下一结点的关系,具体如下:
- 当第一个结点和第二个结点相等,用temp保存后第二个结点,让它只要不为None,并且它所到的结点等于temp,就不断的移动,退出循环,调用递归,让它从 pHead.next再开始判断
- 当第一个结点和第二个结点不相等,pHead向后移动一位,调用递归来判断下一位和它的下一位的关系,如果都不相等,直接走到末尾,就返回头结点即可
# -*- coding:utf-8 -*-
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def deleteDuplication(self, pHead):
if not pHead or not pHead.next:
return pHead
if pHead.val == pHead.next.val:
temp = pHead.next
while temp and temp.val == pHead.val:
temp = temp.next
return self.deleteDuplication(temp)
else:
pHead.next = self.deleteDuplication(pHead.next)
return pHead