day 3 任务以及具体安排:第二章 链表part01

第一题:203. 移除链表元素 - 力扣(LeetCode)

解题思路

本题要求删除链表中所有值等于给定 val 的节点,并返回新的头节点。关键在于如何高效且统一地处理头节点和其他节点的删除操作。以下是详细思路:

  1. 虚拟头节点(Dummy Node)

    • 使用虚拟头节点可以避免对头节点的特殊处理。例如,当原链表的头节点需要被删除时,直接通过修改虚拟头节点的 next 即可,无需额外判断。
    • 虚拟头节点的初始 next 指向原链表的头节点,这样整个链表的操作可以统一为对后续节点的处理
  2. 遍历与删除逻辑

    • 使用指针 cur 从虚拟头节点开始遍历链表。
    • 在每次循环中,检查 cur.next 的值是否等于目标值 target
      • 如果等于目标值,则跳过该节点:cur.next = cur.next.next
      • 如果不等于目标值,则将 cur 移动到下一个节点。
    • 这样可以确保所有符合条件的节点都被删除,并且链表结构保持正确
  3. 边界情况处理

    • 空链表 :直接返回 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)

解题思路

迭代法(双指针)
  1. 核心思想 :使用两个指针 curpre,逐个反转链表中的节点指针。
    • cur 指向当前节点,pre 指向前一个节点。
    • 在遍历链表时,将当前节点的 next 指针指向 pre,实现反转。
    • 然后移动 precur 指针,直到遍历完整个链表。
  2. 边界处理
    • 初始时,prenullcur 为头节点 head
    • curnull 时,pre 即为新的头节点。
递归法
  1. 核心思想 :通过递归将问题分解为子问题,逐步反转链表。
    • 假设当前节点 cur 后面的所有节点已经反转完成,只需将 curnext 指针指向 pre
    • 递归终止条件:当 curnull 时,返回 pre 作为新的头节点。
  2. 递归逻辑
    • 保存当前节点的下一个节点 temp
    • cur.next 指向 pre
    • 递归处理 tempcur,即反转剩余部分。

 

/**
 * 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);
    }
}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值