案例
给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。
示例 1:
输入:head = [1,2,3,4,5], n = 2
输出:[1,2,3,5]
示例 2:
输入:head = [1], n = 1
输出:[]
示例 3:
输入:head = [1,2], n = 1
输出:[1]
实现思路:
- 如果链表为空或者 n 大于链表长度,直接返回头节点。
- 初始化两个指针 fast 和 slow ,都指向头节点。
- 将 fast 指针向前移动 n 步。
- 如果 fast 指针已经到达链表末尾,说明要删除的是头节点,直接返回头节点的下一个节点。
- 同时移动 fast 和 slow 指针,直到 fast 指针到达链表末尾。
- 删除 slow 指针的下一个节点,并更新 slow 指针的 next 指针。
- 返回头节点。
/**
* Definition for singly-linked list.
* public 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) {
ListNode dummy = new ListNode(0);
dummy.next = head;
ListNode first = dummy;
ListNode second = dummy;
for (int i = 0; i <= n; i++) {
first = first.next;
}
while (first != null) {
first = first.next;
second = second.next;
}
second.next = second.next.next;
return dummy.next;
}
}
链表的基本概念与特点
- 链表的定义:动态数据结构,通过节点存储数据和指针链接
- 与数组的对比:内存分配方式、插入/删除效率、随机访问性能
- 单向链表、双向链表、循环链表的类型区分
Java中的链表实现
java.util.LinkedList类的基本介绍- 自定义链表节点类的代码示例
class Node<T> {
T data;
Node<T> next;
// 双向链表增加 prev 指针
}
核心操作实现(代码示例)
插入操作
- 头插法
void insertAtHead(T data) {
Node<T> newNode = new Node<>(data);
newNode.next = head;
head = newNode;
}
- 尾插法
- 指定位置插入
删除操作
- 删除头节点
- 删除指定值节点
void deleteNode(T key) {
Node<T> temp = head, prev = null;
while (temp != null && !temp.data.equals(key)) {
prev = temp;
temp = temp.next;
}
if (temp == null) return;
prev.next = temp.next;
}
常见算法问题
- 反转链表(迭代与递归实现)
- 检测环(快慢指针法)
- 合并两个有序链表
- 查找中间节点
性能优化与实践建议
- 虚拟头节点(Dummy Node)的应用场景
- 内存泄漏防范:Java的垃圾回收机制与链表节点引用
- 线程安全考虑:
ConcurrentLinkedQueue的替代方案
实际应用场景
- LRU缓存淘汰算法中的双向链表应用
- 多项式运算的链表存储实现
- 区块链中的默克尔树与链表结构关联

被折叠的 条评论
为什么被折叠?



