2、链表

代码随想录
LeetCode 题解
链表
递归链表
在链表中穿针引线

1、移除链表元素

203 - 移除链表元素

public ListNode removeElements(ListNode head, int val) {
    ListNode dummyHead = new ListNode(-1, head);

    ListNode prev = dummyHead;
    while (prev.next != null) {
        if (prev.next.val == val) prev.next = prev.next.next;
        else prev = prev.next;
    }

    return dummyHead.next;
}
public static ListNode removeElements(ListNode head, int val) {
    if (head == null) return null;
    head.next = removeElements(head.next, val);
    return head.val != val ? head : head.next;
}

2、设计链表

707 - 设计链表

public class MyLinkedList {

    private class Node {
        int val;
        Node next;

        public Node() {
        }

        public Node(int val, Node next) {
            this.val = val;
            this.next = next;
        }
    }

    private Node dummyHead;
    int size;

    public MyLinkedList() {
        dummyHead = new Node();
        size = 0;
    }

    public int get(int index) {
        if (index < 0 || index >= size) return -1;

        Node cur = dummyHead.next;
        for (int i = 0; i < index; i++) {
            cur = cur.next;
        }

        return cur.val;
    }

    public void addAtHead(int val) {
        addAtIndex(0, val);
    }

    public void addAtTail(int val) {
        addAtIndex(size, val);
    }

    public void addAtIndex(int index, int val) {
        if (index < 0 || index > size) return;

        Node prev = dummyHead;
        for (int i = 0; i < index; i++) prev = prev.next;
        prev.next = new Node(val, prev.next);
        size++;
    }

    public void deleteAtIndex(int index) {
        if (index < 0 || index >= size) return;

        Node prev = dummyHead;
        for (int i = 0; i < index; i++) {
            prev = prev.next;
        }
        prev.next = prev.next.next;
        size--;
    }
}

3、反转链表

206 - 反转链表

public ListNode reverseList(ListNode head) {
    ListNode prev = null;
    ListNode cur = head;
    ListNode next;

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

    return prev;
}
public ListNode reverseList(ListNode node) {
    if (node == null || node.next == null) return node;

    ListNode head = reverseList(node.next);
    node.next.next = node;
    node.next = null;

    return head;
}

4、两两交换链表中的节点

24 - 两两交换链表中的节点

public ListNode swapPairs(ListNode head) {
    if (head == null || head.next == null) return head;
    ListNode dummyHead = new ListNode(-1, head);

    // 1 -> 2 -> 3 -> 4 -> 5 -> 6
    // 2 -> 1 -> 4 -> 3 -> 6 -> 5
    ListNode prev = dummyHead;
    ListNode node1 = head;
    ListNode node2 = head.next;
    ListNode next;
    while (node1 != null && node2 != null) {
        next = node2.next;
        node2.next = node1;
        node1.next = next;
        prev.next = node2;

        prev = node1;
        node1 = next;
        if (node1 != null) node2 = node1.next;
    }

    return dummyHead.next;
}
public ListNode swapPairs(ListNode node) {
    if (node == null || node.next == null) return node;

    ListNode node1 = node;
    ListNode node2 = node.next;

    ListNode res = swapPairs(node2.next);
    node2.next = node1;
    node1.next = res;

    return node2;
}

5、删除链表的倒数第 N 个节点

19 - 删除链表的倒数第 N 个结点

public ListNode removeNthFromEnd(ListNode head, int n) {
    ListNode dummyHead = new ListNode(-1, head);

    ListNode p1 = dummyHead;
    ListNode p2 = dummyHead;
    // 让 p2 向后移动 n + 1 次
    for (int i = 0; i < n + 1; i++) p2 = p2.next;

    while (p2 != null) {
        p1 = p1.next;
        p2 = p2.next;
    }
    p1.next = p1.next.next;

    return dummyHead.next;
}

6、链表相交

面试题 02.07 - 链表相交
题解

image

public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
    ListNode h1 = headA;
    ListNode h2 = headB;

    while (h1 != h2) {
        h1 = h1 != null ? h1.next : headB;
        h2 = h2 != null ? h2.next : headA;
    }

    return h1;
}

7、环形链表 II

142 - 环形链表 II
题解

image

慢指针 slow 每次走 1 步
快指针 fast 每次走 2 步

f = 2 * s(快指针每次 2 步,路程是慢指针的 2 倍)
f = s + nb(相遇时,快指针比慢指针多走了 n 圈)
推出:s = nb

从 head 节点走到入环点需要走:a + nb, 而 slow 已经走了 nb,那么 slow 再走 a 步就是入环点了
如何知道 slow 刚好走了 a 步:fast 从 head 开始,和 slow 指针一起走,相遇时刚好就是 a 步
public ListNode detectCycle(ListNode head) {
    ListNode slow = head;
    ListNode fast = head;

    while (true) {
        if (fast == null || fast.next == null) return null; // 无环
        slow = slow.next;
        fast = fast.next.next;
        if (slow == fast) break;
    }

    fast = head;
    while (slow != fast) {
        slow = slow.next;
        fast = fast.next;
    }

    return slow;
}
posted @ 2023-05-29 15:39  lidongdongdong~  阅读(5)  评论(0编辑  收藏  举报