leetcode链表相关题目

1. 链表反转系列

1.1 反转链表

leetcode206

1.1.1 迭代版

public ListNode reverseList(ListNode head) {
    ListNode newHead = null; // 指向新链表头节点的指针
    while (head != null) {
        ListNode next = head.next; // 备份head.next
        head.next = newHead; // 更新head.next
        newHead = head; // 移动newHead
        head = next; // 遍历链表
    }
    return newHead; // 返回新链表头节点
}

1.1.2 递归版

public ListNode reverseList(ListNode head) {
    if (head == null || head.next == null) {
        return head;
    }
    ListNode cur = reverseList(head.next); // cur尾节点
    // 1->2->3->4->5 head为4 cur为5
    head.next.next = head; // 5->4
    head.next = null; // 删除4->5
    return cur;
}

1.2 反转链表II

leetcode92

1.2.1 迭代版

public ListNode reverseBetween(ListNode head, int m, int n) {
    ListNode dummy = new ListNode(-1);
    ListNode pre = dummy;
    dummy.next = head;

    for (int i = 0; i < m - 1; i++) pre = pre.next;
    ListNode cur = pre.next;
    for (int i = m; i < n; i++) {
        ListNode t = cur.next;
        cur.next = t.next;
        t.next = pre.next;
        pre.next = t;
    }
    return dummy.next;
}

1.2.2 递归版

public ListNode reverseBetween(ListNode head, int m, int n) {
    if (m == 1) {
        return reverseN(head, n);
    }
    head.next = reverseBetween(head.next, m - 1, n - 1);
    return head;
}

private ListNode next = null;

private ListNode reverseN(ListNode head, int n) {
    if (n == 1) {
        next = head.next;
        return head;
    }
    ListNode last = reverseN(head.next, n - 1);
    head.next.next = head;
    head.next = next;
    return last;
}

1.3 两两交换链表中的节点

leetcode24

1.3.1 迭代版

public ListNode swapPairs(ListNode head) {
    // 按原始链表顺序调整指针
    if (head == null || head.next == null) return head;

    ListNode node = new ListNode(-1);
    ListNode res = node;

    while (head != null && head.next != null) {
        node.next = head.next;
        head.next = head.next.next;
        node.next.next = head;

        node = head;
        head = head.next;
    }
    return res.next;
}

1.3.2 递归版

public ListNode swapPairs(ListNode head) {
    if (head == null || head.next == null) return head;

    ListNode node = head.next;
    head.next = swapPairs(node.next);
    node.next = head;
    return node;
}

1.4 K个一组翻转链表

leetcode25

public ListNode reverseKGroup(ListNode head, int k) {
    if (head == null || head.next == null) return head;
    ListNode tail = head;
    for (int i = 0; i < k; i++) {
        if (tail == null) return head;
        tail = tail.next;
    }
    ListNode newHead = reverse(head, tail);
    head.next = reverseKGroup(tail, k);

    return newHead;
}

private ListNode reverse(ListNode head, ListNode tail) {
    ListNode pre = null;
    ListNode next = null;
    while (head != tail) {
        next = head.next;
        head.next = pre;
        pre = head;
        head = next;
    }
    return pre;
}

1.5 回文链表

leetcode234

public boolean isPalindrome(ListNode head) {
    ListNode slow = head, fast = head;
    while (fast != null && fast.next != null) {
        slow = slow.next;
        fast = fast.next.next;
    }

    slow = reverseList(fast == null ? slow : slow.next);
    while (slow != null) {
        if (slow.val != head.val) return false;
        slow = slow.next;
        head = head.next;
    }
    return true;
}

private ListNode reverseList(ListNode head) {
    if (head == null || head.next == null) {
        return head;
    }
    ListNode cur = reverseList(head.next); // cur尾节点
    // 1->2->3->4->5 head为4 cur为5
    head.next.next = head; // 5->4
    head.next = null; // 删除4->5
    return cur;
}

2. 链表排序系列

2.1 合并有序链表

leetcode21

public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
    if (l1 == null) return l2;
    if (l2 == null) return l1;
    if (l1.val < l2.val) {
        l1.next = mergeTwoLists(l1.next, l2);
        return l1;
    } else {
        l2.next = mergeTwoLists(l1, l2.next);
        return l2;
    }
}

2.2 合并K个有序链表

leetcode23

public ListNode mergeKLists(ListNode[] lists) {
    if (lists.length == 0) return null;
    return solve(lists, 0, lists.length - 1);
}

private ListNode solve(ListNode[] arr, int left, int right) {
    if (left == right) return arr[left];
    int mid = (left + right) >> 1;
    ListNode lNode = solve(arr, left, mid);
    ListNode rNode = solve(arr, mid + 1, right);

    return mergeTwoLists(lNode, rNode);
}

private ListNode mergeTwoLists(ListNode l1, ListNode l2) {
    if (l1 == null) return l2;
    if (l2 == null) return l1;
    if (l1.val < l2.val) {
        l1.next = mergeTwoLists(l1.next, l2);
        return l1;
    } else {
        l2.next = mergeTwoLists(l1, l2.next);
        return l2;
    }
}

2.3 排序链表

leetcode148

public ListNode sortList(ListNode head) {
    if (head == null || head.next == null) return head;

    ListNode mid = findMiddle(head);
    ListNode right = sortList(mid.next);
    mid.next = null;
    ListNode left = sortList(head);

    return merge(left, right);
}

private ListNode findMiddle(ListNode head) {
    ListNode slow = head, fast = head;
    while (fast.next != null && fast.next.next != null) {
        slow = slow.next;
        fast = fast.next.next;
    }
    return slow;
}

private ListNode merge(ListNode l1, ListNode l2) {
    if (l1 == null) return l2;
    if (l2 == null) return l1;
    if (l1.val < l2.val) {
        l1.next = merge(l1.next, l2);
        return l1;
    } else {
        l2.next = merge(l1, l2.next);
        return l2;
    }
}

2.4 重排链表

leetcode143

public void reorderList(ListNode head) {
    if (head == null || head.next == null) return;
    ListNode slow = head, fast = head;
    while (fast.next != null && fast.next.next != null) {
        slow = slow.next;
        fast = fast.next.next;
    }
    slow.next = reverseList(slow.next);

    while (slow.next != null && head != null) {
        ListNode cur = slow.next;
        slow.next = cur.next;
        ListNode t = head.next;
        head.next = cur;
        cur.next = t;
        head = head.next.next;
    }
}

private ListNode reverseList(ListNode head) {
    if (head == null || head.next == null) {
        return head;
    }
    ListNode cur = reverseList(head.next); // cur尾节点
    // 1->2->3->4->5 head为4 cur为5
    head.next.next = head; // 5->4
    head.next = null; // 删除4->5
    return cur;
}

2.5 删除排序链表中的重复元素

leetcode83

public ListNode deleteDuplicates(ListNode head) {
    if (head == null || head.next == null) return head;
    ListNode dummy = new ListNode(-1024);
    dummy.next = head;
    ListNode pre = dummy;

    while (head != null) {
        if (head.val == pre.val) {
            pre.next = head.next;
            head.next = null;
            head = pre.next;
        } else {
            pre = head;
            head = head.next;
        }
    }
    return dummy.next;
}

2.6 删除排序链表中的重复元素II

leetcode82

public ListNode deleteDuplicates(ListNode head) {
    if (head == null || head.next == null) return head;
    
    if (head.val == head.next.val) {
        ListNode pNode = head.next;
        while (pNode != null && pNode.val == head.val) pNode = pNode.next;
        return deleteDuplicates(pNode);
    } else {
        head.next = deleteDuplicates(head.next);
        return head;
    }
}

3. 链表删除系列

3.1 删除链表中的节点

leetcode237

public void deleteNode(ListNode node) {
    node.val = node.next.val;
    node.next = node.next.next;
}

3.2 删除链表倒数第N个节点

leetcode19

public ListNode removeNthFromEnd(ListNode head, int n) {
    ListNode dummy = new ListNode(0);
    dummy.next = head;
    ListNode slow = dummy, fast = dummy;
    for (int i = 0; i <= n; i++) fast = fast.next;

    while (fast != null) {
        fast = fast.next;
        slow = slow.next;
    }
    slow.next = slow.next.next;
    return dummy.next;
}

3.3 查找倒数第K个节点

public ListNode FindKthToTail(ListNode head, int k) {
    ListNode fast, slow;
    fast = slow = head;
    int i = 0;
    for (; fast != null; i++) {
        if (i >= k) slow = slow.next;
        fast = fast.next;
    }
    return i < k ? null : slow;
}

3.4 移除链表元素

leetcode203

public ListNode removeElements(ListNode head, int val) {
    ListNode dummy = new ListNode(-1);
    dummy.next = head;
    ListNode pre = dummy;

    while (head != null) {
        if (head.val == val) {
            pre.next = head.next;
            head.next = null;
            head = pre.next;
        } else {
            pre = head;
            head = head.next;
        }
    }
    return dummy.next;
}

4. 查找中间节点

public static int findMidNode(Node head) {
    if (head == null)
        return -1;
    Node fast = head, slow = head;
    while (fast != null && fast.next != null) {
        slow = slow.next;
        fast = fast.next.next;
    }
    return slow.val;
}

5. 从尾到头打印链表

private ArrayList<Integer> res = new ArrayList<>();

public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
    if (listNode == null) return res;
    printListFromTailToHead(listNode.next);
    res.add(listNode.val);
    return res;
}

6. 相交链表

leetcode160

public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
    if (headA == null || headB == null) return null;
    ListNode ptrA = headA;
    ListNode ptrB = headB;
    while (ptrA != ptrB) {
        ptrA = ptrA != null ? ptrA.next : headB;
        ptrB = ptrB != null ? ptrB.next : headA;
    }
    return ptrA;
}

7. 分割链表

leetcode86

public ListNode partition(ListNode head, int x) {
    ListNode before_head = new ListNode(0);
    ListNode before = before_head;
    ListNode after_head = new ListNode(0);
    ListNode after = after_head;

    while (head != null) {
        if (head.val < x) {
            before.next = head;
            before = before.next;
        } else {
            after.next = head;
            after = after.next;
        }
        head = head.next;
    }

    after.next = null;
    before.next = after_head.next;
    return before_head.next;
}

8. 复杂链表的复制

leetcode138

public Node copyRandomList(Node head) {
    if (head == null) return null;
    Node dummy = head;
    while (dummy != null) {
        Node t = new Node(dummy.val);
        t.next = dummy.next;
        dummy.next = t;
        dummy = t.next;
    }

    dummy = head;
    while (dummy != null) {
        if (dummy.random != null) {
            dummy.next.random = dummy.random.next;
        }
        dummy = dummy.next.next;
    }

    dummy = head;
    Node res = head.next;
    while (dummy.next != null) {
        Node t = dummy.next;
        dummy.next = dummy.next.next;
        dummy = t;
    }
    return res;
}

9. 两数相加

leetcode2

public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
    int k1 = getLength(l1);
    int k2 = getLength(l2);
    if (k1 < k2) { // 保证l1指向长链表
        ListNode t = l1;
        l1 = l2;
        l2 = t;
    }
    boolean flag = false;
    ListNode res = l1;
    ListNode pre = null;
    while (l1 != null) {
        if (l1.next == null) pre = l1;
        int k = l1.val + (l2 == null ? 0 : l2.val) + (flag ? 1 : 0);
        flag = k >= 10;
        l1.val = k % 10;
        l1 = l1.next;
        if (l2 != null) l2 = l2.next;
    }
    if (flag) pre.next = new ListNode(1);

    return res;
}

private int getLength(ListNode head) {
    int count = 0;
    while (head != null) {
        count++;
        head = head.next;
    }
    return count;
}

10. 两数相加II

leetcode445

public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
    Stack<Integer> s1 = pushStack(l1);
    Stack<Integer> s2 = pushStack(l2);

    boolean flag = false;
    ListNode pre = null;
    while (!s1.isEmpty() || !s2.isEmpty()) {
        int sum = (s1.isEmpty() ? 0 : s1.pop()) + (s2.isEmpty() ? 0 : s2.pop()) + (flag ? 1 : 0);
        flag = (sum >= 10);
        ListNode node = new ListNode(sum % 10);
        node.next = pre;
        pre = node;
    }
    if (flag) {
        ListNode newHead = new ListNode(1);
        newHead.next = pre;
        pre = newHead;
    }
    return pre;
}

private Stack<Integer> pushStack(ListNode head) {
    Stack<Integer> stack = new Stack<>();
    while (head != null) {
        stack.push(head.val);
        head = head.next;
    }
    return stack;
}

11. 奇偶链表

leetcode328

public ListNode oddEvenList(ListNode head) {
    if (head == null || head.next == null) return head;
    
    ListNode m = head;
    ListNode n = head.next;
    ListNode t = head.next;
    while (m.next != null) {
        m.next = n.next;
        if (n.next != null) {
            n.next = m.next.next;
        }
        if (m.next != null) {
            m = m.next;
        }
        n = n.next;
    }
    m.next = t;
    return head;
}

12. 有序链表转二叉搜索树

leetcode109

posted @ 2020-06-17 16:48  sakura1027  阅读(149)  评论(0编辑  收藏  举报