算法-链表实战【删除链表的倒数第 N 个结点】中等

删除链表的倒数第 N 个结点

提示 给你一个链表,删除链表的倒数第 n个结点,并且返回链表的头结点。

示例 1:

ini 复制代码
输入: head = [1,2,3,4,5], n = 2
输出: [1,2,3,5]

示例 2:

ini 复制代码
输入: head = [1], n = 1
输出: []

示例 3:

ini 复制代码
输入: head = [1,2], n = 1
输出: [1]

提示:

  • 链表中结点的数目为 sz
  • 1 <= sz <= 30
  • 0 <= Node.val <= 100
  • 1 <= n <= sz

进阶: 你能尝试使用一趟扫描实现吗?

解答

核心思路:​快慢双指针法​

--->使用两个指针(快慢指针),让快指针先走 N 步,然后两个指针同步移动。当快指针到达尾部时,慢指针正好指向倒数第 N 个节点的前驱节点,完成删除操作。

ini 复制代码
class ListNode {
    int val;
    ListNode next;
    ListNode() {}
    ListNode(int val) { this.val = val; }
    ListNode(int val, ListNode next) { this.val = val; this.next = next; }
}

class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        // 1. 创建哑节点(哨兵节点),用于处理头节点删除情况
        ListNode dummy = new ListNode(0);
        dummy.next = head;
        
        // 2. 初始化快慢指针,都从哑节点开始
        ListNode fast = dummy;
        ListNode slow = dummy;
        
        // 3. 快指针先走 N 步
        for (int i = 0; i <= n; i++) {
            fast = fast.next;
        }
        
        // 4. 同步移动快慢指针
        while (fast != null) {
            fast = fast.next;
            slow = slow.next;
        }
        
        // 5. 删除倒数第 N 个节点
        slow.next = slow.next.next;
        
        // 6. 返回新头节点(始终是 dummy.next)
        return dummy.next;
    }
}

示例说明(以输入head = [1,2,3,4,5], n=2为例)

  1. 创建哑节点 :dummy(0) -> 1 -> 2 -> 3 -> 4 -> 5
  2. 初始化指针 :fast和slow都指向dummy(0)
  3. 快指针移动n+1=3步 :
    • 第一次:fast=1
    • 第二次:fast=2
    • 第三次:fast=3
  4. 同时移动 :
    • 快指针从3开始移动到尾部(4,5,null),慢指针从0开始移动到1,2,3。当快指针为null时,慢指针在3的位置
  5. 删除节点 :slow(3)的下一个节点是4(即倒数第2个节点),修改其next指向5,链表变为dummy(0)->1->2->3->5
  6. 返回 :dummy.next=1,即返回[1,2,3,5]

完整算法步骤

  1. 创建哑节点 :
    • 新建一个哑节点dummy,并将其next指向链表的头节点。
  2. 初始化两个指针 :
    • fast(快指针)和slow(慢指针),都指向哑节点。
  3. 快指针先移动N+1步 :
    • 这样快指针和慢指针之间就保持了N+1个节点的距离。当快指针移动到链表末尾时,慢指针刚好指向待删除节点的前驱节点。
  4. 同时移动快指针和慢指针 :
    • 当快指针不为null时,快慢指针同时向后移动一步,直到快指针指向null(即快指针到达链表尾部)。
  5. 删除节点 :
    • 此时慢指针slow指向待删除节点的前一个节点,将slow.next指向slow.next.next,就删除了倒数第N个节点。
  6. 返回新链表的头节点 :
    • 返回哑节点dummy的next,即新链表的头节点。
相关推荐
nice_lcj52015 小时前
LRU 缓存入门:它是什么、怎么用、面试怎么手写
java·数据结构·缓存·面试·lru
꧁细听勿语情꧂15 小时前
直接选择排序,堆排序,冒泡排序,递归快速排序、hoare版本、挖坑法、lomuto前后指针,非递归快速排序
c语言·开发语言·数据结构·算法
Pniubi1 天前
关于算法用现成数据结构和手撕
数据结构
老师我太想进步了20262 天前
【数据结构-6】算法美学之单链表(1)
数据结构·算法
希望我万事顺遂2 天前
力扣hot100-滑动窗口最大值
数据结构·算法·leetcode
꧁细听勿语情꧂2 天前
二叉树余题,排序、直接插入排序、希尔排序
c语言·开发语言·数据结构·算法
是main不是漫2 天前
【双指针|LeetCode1089 复写零】巧用逆向思路,破解原地覆盖陷阱
数据结构·算法·leetcode
饮水桶_T2 天前
JAVA IO流笔记
开发语言·数据结构·算法
wo_jack3 天前
C++ 入门笔记(十七):list 入门 —— 为什么 list 不能 sort?
数据结构·c++·面试·stl·list
zaizai10073 天前
算法(左程云)1
数据结构