第一题:203. 移除链表元素 - 力扣(LeetCode)
解题思路
本题要求删除链表中所有值等于给定 val 的节点,并返回新的头节点。关键在于如何高效且统一地处理头节点和其他节点的删除操作。以下是详细思路:
-
虚拟头节点(Dummy Node) :
- 使用虚拟头节点可以避免对头节点的特殊处理。例如,当原链表的头节点需要被删除时,直接通过修改虚拟头节点的
next即可,无需额外判断。 - 虚拟头节点的初始
next指向原链表的头节点,这样整个链表的操作可以统一为对后续节点的处理
- 使用虚拟头节点可以避免对头节点的特殊处理。例如,当原链表的头节点需要被删除时,直接通过修改虚拟头节点的
-
遍历与删除逻辑 :
- 使用指针
cur从虚拟头节点开始遍历链表。 - 在每次循环中,检查
cur.next的值是否等于目标值target:- 如果等于目标值,则跳过该节点:
cur.next = cur.next.next。 - 如果不等于目标值,则将
cur移动到下一个节点。
- 如果等于目标值,则跳过该节点:
- 这样可以确保所有符合条件的节点都被删除,并且链表结构保持正确
- 使用指针
-
边界情况处理 :
- 空链表 :直接返回
dummy.next(即null)。 - 全链表删除 :如所有节点值均为
val,虚拟头节点的next会最终指向null。 - 连续删除 :如链表中有连续多个目标节点,通过不断修改前驱节点的
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 removeElements(ListNode head, int target) {
// 创建虚拟头节点,next指向原链表的头节点
ListNode dummy = new ListNode();
dummy.next = head;
// 当前指针cur从虚拟头节点开始
ListNode cur = dummy;
// 遍历链表,直到cur.next为空(即到达链表末尾)
while (cur.next != null) {
// 如果当前节点的下一个节点值等于目标值target
if (cur.next.val == target) {
// 跳过该节点,将cur.next指向下一个节点的下一个节点
cur.next = cur.next.next;
// 注意:这里不移动cur指针,因为可能需要继续检查新的cur.next是否为目标值
} else {
// 如果当前节点不需要删除,移动cur指针到下一个节点
cur = cur.next;
}
}
// 返回新的头节点,即虚拟头节点的下一个节点
return dummy.next;
}
}
第二题:206. 反转链表 - 力扣(LeetCode)
解题思路
迭代法(双指针)
- 核心思想 :使用两个指针
cur和pre,逐个反转链表中的节点指针。cur指向当前节点,pre指向前一个节点。- 在遍历链表时,将当前节点的
next指针指向pre,实现反转。 - 然后移动
pre和cur指针,直到遍历完整个链表。
- 边界处理 :
- 初始时,
pre为null,cur为头节点head。 - 当
cur为null时,pre即为新的头节点。
- 初始时,
递归法
- 核心思想 :通过递归将问题分解为子问题,逐步反转链表。
- 假设当前节点
cur后面的所有节点已经反转完成,只需将cur的next指针指向pre。 - 递归终止条件:当
cur为null时,返回pre作为新的头节点。
- 假设当前节点
- 递归逻辑 :
- 保存当前节点的下一个节点
temp。 - 将
cur.next指向pre。 - 递归处理
temp和cur,即反转剩余部分。
- 保存当前节点的下一个节点
/**
* 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 reverseList(ListNode head) {
// 初始时,pre为null,cur为头节点
return reverse(head, null);
}
/**
* 迭代法(双指针):
* 时间复杂度 O(n),空间复杂度 O(1)
*/
private ListNode reverse(ListNode cur, ListNode pre) {
while (cur != null) {
// 保存当前节点的下一个节点
ListNode temp = cur.next;
// 反转当前节点的指针,指向pre
cur.next = pre;
// 移动指针:pre变为当前节点,cur变为下一个节点
pre = cur;
cur = temp;
}
// 当循环结束时,pre为新的头节点
return pre;
}
/**
* 递归法:
* 时间复杂度 O(n),空间复杂度 O(n)(递归栈)
*/
private ListNode reverse(ListNode cur, ListNode pre) {
// 递归终止条件:当cur为空时返回pre作为新头节点
if (cur == null) {
return pre;
}
// 保存当前节点的下一个节点
ListNode temp = cur.next;
// 反转当前节点的指针,指向pre
cur.next = pre;
// 递归处理下一个节点,pre变为当前节点cur,cur变为temp
return reverse(temp, cur);
}
}
697

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



