Leetcode尊享面试100题【Part4 链表】【题目+分析+答案】

文章介绍了如何在LeetCode中实现链表的反转操作,如给定单链表的头节点,反转链表并返回新的头节点。同时,也详细讲解了删除链表中特定数量节点的方法,通过哑节点简化处理边界情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在这里插入图片描述

4 链表

链表是物理存储单元上非连续的、非顺序的存储结构,数据元素的逻辑顺序是通过链表的指针地址实现。

结点包括两个部分:(1)存储数据元素的数据域(内存空间),(2)存储指向下一个结点地址的指针域。

链表分为: (1)单链表 (2)双链表 (3)单向循环链表 (4)双向循环链表

4.1 举例: 反转链表
给你单链表的头节点 head ,请你反转链表,并返回反转后的链表

输入:head = [1,2,3,4,5]
输出:[5,4,3,2,1]


输入:head = [1,2]
输出:[2,1]
示例 3:

输入:head = []
输出:[]

根据链表的定义,其每个节点都包含两个域,一个为信息域:存储元素,一个为链接域:存储下一节点的地址,最后一个节点的链接域指向一个空值。

每一步循环中,都将原列表中cur.next链接域存放的地址指向其前一个节点,直至cur=Null,pre指向最后一个节点。

循环后,原链表中,最后一个节点中指向的下一个节点为原倒数第二个节点,以此类推,原列表的第一个节点指向Null;pre即相当于头节点,返回pre,相当于将原链表反转

1、迭代需要三个指针,pre,cur,nxt,分别按顺序指向三个节点
2、三个指针的初始化:pre指向空节点,cur指向头结点head,nxt指向head.next; 因为head.next可能不存在,nxt在循环中定义,这样如果head为空就不会进入循环
3、迭代过程

  • nxt指向cur.next
  • cur.next指向pre
  • pre移动到cur位置
  • cur移动到nxt位置

4、当cur为空时,返回pre

在这里插入图片描述

class Solution:
    def reverseList(self, head: ListNode) -> ListNode:
        pre = None
        cur = head
        while cur:
            next_temp= cur.next #保存当前节点的下一个节点,防止丢失
            cur.next = pre #将当前节点的指针指向前一个节点,实现反转操作 next用来存放下一个节点的位置
            
            #指针存放地址(位置信息) pre cur的位置信息向前移
            pre = cur #将 pre 指针指向当前节点,为下一次迭代做准备
            cur = next_temp #将当前节点指针移动到下一个节点。
        return pre 

4.1 删除链表 M 个节点之后的 N 个节点

题目描述
给定链表 head 和两个整数 mn. 遍历该链表并按照如下方式删除节点:

  • 开始时以头节点作为当前节点.
  • 保留以当前节点开始的前 m 个节点.
  • 删除接下来的 n 个节点.
  • 重复步骤 2 和 3, 直到到达链表结尾.
    在删除了指定结点之后, 返回修改过后的链表的头节点.

在这里插入图片描述

示例 1:
输入: head = [1,2,3,4,5,6,7,8,9,10,11,12,13], m = 2, n = 3
输出: [1,2,6,7,11,12]
解析: 保留前(m = 2)个结点,  也就是以黑色节点表示的从链表头结点开始的结点(1 ->2).
删除接下来的(n = 3)个结点(3 -> 4 -> 5), 在图中以红色结点表示.
继续相同的操作, 直到链表的末尾.
返回删除结点之后的链表的头结点.

在这里插入图片描述

示例 2:
输入: head = [1,2,3,4,5,6,7,8,9,10,11], m = 1, n = 3
输出: [1,5,9]
解析: 返回删除结点之后的链表的头结点.
示例 3:
输入: head = [1,2,3,4,5,6,7,8,9,10,11], m = 3, n = 1
输出: [1,2,3,5,6,7,9,10,11]

示例 4:
输入: head = [9,3,7,7,9,10,8,2], m = 1, n = 2
输出: [9,7,8]

思路分析
哑节点(dummy node)是在链表的头部或尾部添加一个额外的节点,用于简化链表操作和处理边界情况。它不存储具体的数据,只起到一个辅助作用

代码描述

class Solution:
    def deleteNodes(self, head: ListNode, m: int, n: int) -> ListNode:
        if not head:
            return None

        # 创建一个哑节点作为新链表的头部
        dummy = ListNode(0)
        #将哑节点的下一个指针指向原链表的头部。
        dummy.next = head

        # 定义两个指针,cur用于遍历链表,prev用于连接前后节点
        cur = dummy
        prev = dummy
		
		#当 当前节点不为空时,进入循环
        while cur:
            # 保留前m个节点
            # 每经过一个节点,cur和prev指针都向后移动一位
            for _ in range(m):
                if cur:
                    prev = cur
                    cur = cur.next
            
            # 删除接下来的n个节点
            # 删除接下来的n个节点,每删除一个节点,cur指针向后移动一位。
            for _ in range(n):
                if cur and cur.next:
                    cur.next = cur.next.next
                else:
                    break
        
            # 进入下一轮迭代
            #将prev的下一个指针指向当前的cur,连接链表
            prev.next = cur

cur.next = cur.next.next将当前节点的 next 指针指向当前节点的下一个节点的下一个节点,即跳过了当前节点的下一个节点,实现了删除操作。通过这种方式,将当前节点与下一个节点断开连接,然后让 cur 指针继续指向链表中的下一个节点,达到删除的效果。

例如,如果当前节点是 A,它的下一个节点是 B,我们执行 cur.next = cur.next.next,那么 A 的 next 指针将直接指向 B 的下一个节点,跳过了 B。这样就在不破坏链表结构的情况下,实现了删除 B 节点的操作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大西瓜的科研日记

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值