单链表特定值节点剔除算法详解
需求概述
本题旨在处理单链表数据结构中的清理任务。输入参数包含链表的起始节点引用以及一个指定的整数阈值。核心目标是遍历列表,定位并移除所有节点存储值与该阈值相符的实例,最终返回经过清洗后的新链表头部。
解法一:分情况处理头节点
在不引入辅助节点的情况下,需要特殊关注链表的首部。因为修改普通节点的连接关系通常是通过前驱节点完成的,而头节点没有前驱,其移除操作涉及对头指针的直接赋值。
- 前置调整:循环检查头节点的值,若等于目标值,则将头指针向后移动一位,直到头节点有效或链表为空。
- 主体遍历:使用游标从新的头节点开始,检查其后继节点。若后继节点的值需要被剔除,则修改当前游标的 next 指针跳过该节点;否则游标正常向后移动。
public class ListProcessor {
public static ListNode removeSpecificValue(ListNode root, int target) {
// 预处理头部,移除所有符合条件的头结点
while (root != null && root.value == target) {
root = root.next;
}
if (root == null) return null; // 链表已空
ListNode ptr = root;
while (ptr.next != null) {
if (ptr.next.value == target) {
// 跳过目标节点
ptr.next = ptr.next.next;
} else {
// 移动到下一位
ptr = ptr.next;
}
}
return root;
}
// 标准链表节点定义
static class ListNode {
int value;
ListNode next;
ListNode(int v) { value = v; }
}
public static void main(String[] args) {
// 构造测试数据:1 -> 2 -> 6 -> 3 -> 4 -> 5 -> 6
ListNode n1 = new ListNode(1);
ListNode n2 = new ListNode(2);
ListNode n3 = new ListNode(6);
ListNode n4 = new ListNode(3);
ListNode n5 = new ListNode(4);
ListNode n6 = new ListNode(5);
ListNode n7 = new ListNode(6);
n1.next = n2; n2.next = n3; n3.next = n4;
n4.next = n5; n5.next = n6; n6.next = n7;
System.out.print("处理后结果:");
ListNode result = removeSpecificValue(n1, 6);
while (result != null) {
System.out.print(result.value + " ");
result = result.next;
}
}
}
解法二:利用虚拟头结点统一逻辑
为了消除对首节点的边界判断,可以采用"哨兵模式"(Sentinel Pattern)。创建一个值为任意数的虚拟节点作为新的头,并将其 next 指向原始头节点。这样,原本的头节点就变成了普通中间节点,从而允许使用统一的逻辑来遍历和删除后续节点。算法执行完毕后,返回虚拟节点的下一个即可。
- 创建哨兵:初始化一个 dummy 节点,链接原链表。
- 统一遍历:从 dummy 开始向后扫描,只要后继节点是目标值就进行断链操作,无需额外判断是否为表头。
public class ListProcessor {
public static ListNode removeWithSentinel(ListNode chainHead, int target) {
// 构建虚拟前导节点
ListNode sentinel = new ListNode(0);
sentinel.next = chainHead;
ListNode curr = sentinel;
while (curr.next != null) {
if (curr.next.value == target) {
// 发现目标节点,切断连接
curr.next = curr.next.next;
} else {
// 继续遍历
curr = curr.next;
}
}
// 返回真实的新头节点
return sentinel.next;
}
static class ListNode {
int value;
ListNode next;
ListNode(int v) { value = v; }
}
public static void main(String[] args) {
// 快速构建测试序列 1->2->6->3->4->5->6
ListNode head = createTestChain();
System.out.println("优化版处理结果:");
ListNode cleanedHead = removeWithSentinel(head, 6);
traverseAndPrint(cleanedHead);
}
private static ListNode createTestChain() {
ListNode[] nodes = new ListNode[7];
int[] vals = {1, 2, 6, 3, 4, 5, 6};
for (int i = 0; i < 7; i++) nodes[i] = new ListNode(vals[i]);
for (int i = 0; i < 6; i++) nodes[i].next = nodes[i+1];
return nodes[0];
}
private static void traverseAndPrint(ListNode start) {
ListNode temp = start;
while (temp != null) {
System.out.print(temp.value + " ");
temp = temp.next;
}
}
}
