剑指offer:Python 删除链表中重复的结点 图解 详细思路

题目描述

在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表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
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值