链表-移除链表元素

131 阅读2分钟

LC203 leetcode.cn/problems/re…

解法一

错误示例

 while (cur!=null){
         if (cur.next.val==val) cur.next=cur.next.next;
         cur=cur.next;
         }

乍一看没问题 但连续两个目标值 就会跳过一个

完整示例

public class LC203 {
    /**
     * Definition for singly-linked list node.
     */
    public static class ListNode {
        int val; // 节点的值
        ListNode next; // 指向下一个节点的引用
​
        // 无参构造函数
        ListNode() {}
    
        // 仅初始化节点值的构造函数
        ListNode(int val) { 
            this.val = val; 
        }
    
        // 初始化节点值和下一个节点引用的构造函数
        ListNode(int val, ListNode next) { 
            this.val = val; 
            this.next = next; 
        }
    }
    
    /**
     * 删除链表中等于给定值 val 的所有节点。
     *
     * @param head 链表的头节点
     * @param val 要删除的节点值
     * @return 处理后的链表头节点
     */
    public static ListNode removeElements(ListNode head, int val) {
        // 处理头部连续的目标值
        while (head != null && head.val == val) {
            head = head.next;
        }
    
        // 如果链表为空,返回 null
        if (head == null) return null;
    
        ListNode cur = head;
        // 遍历并处理非头部的节点
        while (cur != null && cur.next != null) {
            if (cur.next.val == val) {
                cur.next = cur.next.next;
            } else {
                cur = cur.next;
            }
        }
        return head;
    }
    
    /**
     * 打印链表中的所有节点值。
     *
     * @param head 链表的头节点
     */
    public static void printList(ListNode head) {
        ListNode current = head;
        while (current != null) {
            System.out.print(current.val + " -> ");
            current = current.next;
        }
        System.out.println("null");
    }
    
    public static void main(String[] args) {
        // 创建链表节点
        ListNode node1 = new ListNode(1);
        ListNode node2 = new ListNode(2);
        ListNode node3 = new ListNode(2);
        ListNode node4 = new ListNode(1);
    
        // 组装链表
        node1.next = node2;
        node2.next = node3;
        node3.next = node4;
    
        // 打印原始链表
        System.out.print("Original List: ");
        printList(node1);
    
        // 删除值为 2 的节点
        ListNode listNode = removeElements(node1, 2);
    
        // 打印处理后的链表
        System.out.print("Processed List: ");
        printList(listNode);
    }
​
}

解法二 虚拟头节点

public static ListNode removeElements(ListNode head, int val) {
        // 如果链表为空,直接返回 null
        if (head == null)  return null;
        
        // 创建一个虚拟头节点,指向链表的头节点
        ListNode dummyNode = new ListNode(0, head);
​
        ListNode cur = dummyNode;
        // 遍历链表,删除节点值等于 val 的节点
        while (cur != null && cur.next != null) {
            if (cur.next.val == val) {
                cur.next = cur.next.next;
            } else {
                cur = cur.next;
            }
        }
        // 返回处理后的链表头节点
        return dummyNode.next;
    }

相比解法一 不用考虑头节点情况

解法三 递归

非常巧妙

public ListNode removeElements(ListNode head, int val) {
    // 如果链表为空,直接返回 null
    if (head == null) {
        return null;
    }
​
// 递归处理链表的下一个节点
head.next = removeElements(head.next, val);
​
// 如果当前节点的值等于要移除的值,则跳过当前节点,返回下一个节点
if (head.val == val) {
    return head.next;
} else {
    // 否则,保留当前节点,返回当前节点
    return head;
}
​
}

f (head == null) { return null; }

一是指head本身 二是指递归后的head