[链表] - 代码随想录 707. 设计链表
1. 题目要求
在链表类中需要实现以下功能:
get(index):获取链表中第index个节点的值(索引无效时返回-1)addAtHead(val):在链表头部插入值为val的新节点addAtTail(val):在链表尾部追加值为val的新节点addAtIndex(index, val):- 在指定索引
index前插入新节点 - 当
index = 链表长度时插入到末尾 index > 链表长度时不插入index < 0时插入到头部
- 在指定索引
deleteAtIndex(index):删除指定索引的节点(索引无效时不操作)
2. 实现代码
java
/**
* 单链表实现类
* 核心技巧:使用虚拟头节点(dummy head)简化边界处理
*/
class MyLinkedList {
// 虚拟头节点(不存储实际数据)
private Node dummyHead;
// 链表当前长度
private int size;
// 节点内部类
private class Node {
int val;
Node next;
Node(int val, Node next) {
this.val = val;
this.next = next;
}
}
// 构造函数初始化空链表
public MyLinkedList() {
this.dummyHead = new Node(0, null); // 虚拟头节点
this.size = 0; // 初始长度
}
/**
* 获取节点值
* @param index 目标索引(0-indexed)
* @return 值或-1(索引无效时)
*/
public int get(int index) {
// 索引有效性检查
if (index < 0 || index >= size) return -1;
Node curr = dummyHead.next; // 从实际头节点开始
// 遍历到目标节点
for (int i = 0; i < index; i++) {
curr = curr.next;
}
return curr.val;
}
/**
* 头部插入
* 时间复杂度:O(1)
*/
public void addAtHead(int val) {
// 新节点指向原头节点,虚拟头节点指向新节点
dummyHead.next = new Node(val, dummyHead.next);
size++;
}
/**
* 尾部插入
* 时间复杂度:O(n)
*/
public void addAtTail(int val) {
Node curr = dummyHead;
// 遍历到最后一个节点
while (curr.next != null) {
curr = curr.next;
}
// 尾部插入新节点
curr.next = new Node(val, null);
size++;
}
/**
* 指定位置插入
* 处理三种特殊情况:
* 1. index < 0 → 头部插入
* 2. index = size → 尾部插入
* 3. index > size → 不操作
*/
public void addAtIndex(int index, int val) {
// 处理负索引(插入头部)
if (index < 0) {
addAtHead(val);
return;
}
// 超范围索引不操作
if (index > size) return;
Node curr = dummyHead;
// 定位到插入位置的前驱节点
for (int i = 0; i < index; i++) {
curr = curr.next;
}
// 创建新节点并插入
curr.next = new Node(val, curr.next);
size++;
}
/**
* 删除节点
* 注意:需确保前驱节点.next不为空
*/
public void deleteAtIndex(int index) {
// 索引有效性检查
if (index < 0 || index >= size) return;
Node curr = dummyHead;
// 定位到删除位置的前驱节点
for (int i = 0; i < index; i++) {
curr = curr.next;
}
// 跳过目标节点(自动GC回收)
curr.next = curr.next.next;
size--;
}
}
/**
* 使用示例:
* MyLinkedList obj = new MyLinkedList();
* int param_1 = obj.get(index);
* obj.addAtHead(val);
* obj.addAtTail(val);
* obj.addAtIndex(index,val);
* obj.deleteAtIndex(index);
*/
3. 关键实现细节
-
虚拟头节点(dummy head)
- 始终位于链表头部之前,确保空链表操作统一
- 消除头节点操作的特殊逻辑分支
- 插入/删除操作无需单独处理头节点情况
-
时间复杂度控制
操作 时间复杂度 说明 addAtHeadO(1) 直接操作虚拟头节点 getO(n) 需遍历到指定位置 addAtTailO(n) 需遍历到链表末尾 addAtIndexO(n) 需遍历到目标位置前驱节点 deleteAtIndexO(n) 需遍历到目标位置前驱节点 -
边界处理强化
- 所有操作前进行索引有效性验证
addAtIndex明确处理负索引和超范围索引deleteAtIndex确保不操作无效索引
-
结构设计要点
- 内部
Node类封装节点数据与指针 size计数器实时维护链表长度- 所有操作后同步更新
size值
- 内部