Skip to content

25. K 个一组翻转链表

题目描述

给你链表的头节点 head ,每 k 个节点一组进行翻转,请你返回修改后的链表。

k 是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。

你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。

 

示例 1:

image-20240823103414402
输入:head = [1,2,3,4,5], k = 2
输出:[2,1,4,3,5]

示例 2:

image-20240823103436212
输入:head = [1,2,3,4,5], k = 3
输出:[3,2,1,4,5]

 

提示:
  • 链表中的节点数目为 n
  • 1 <= k <= n <= 5000
  • 0 <= Node.val <= 1000

 

进阶:你可以设计一个只用 O(1) 额外内存空间的算法解决此问题吗?

    方法一:迭代

    时间复杂度为 O(n),空间复杂度为 O(1),其中 n 是链表的长度。

    java
    class Solution {
        public ListNode reverseKGroup(ListNode head, int k) {
            ListNode dummy = new ListNode(0, head);
            ListNode pre = dummy, cur = dummy;
            while (cur.next != null) {
                for (int i = 0; i < k && cur != null; ++i) {
                    cur = cur.next;
                }
                if (cur == null) {
                    return dummy.next;
                }
                ListNode t = cur.next;
                cur.next = null;
                ListNode start = pre.next;
                pre.next = reverseList(start);
                start.next = t;
                pre = start;
                cur = pre;
            }
            return dummy.next;
        }
    
        private ListNode reverseList(ListNode head) {
            ListNode pre = null, p = head;
            while (p != null) {
                ListNode q = p.next;
                p.next = pre;
                pre = p;
                p = q;
            }
            return pre;
        }
    }
    ts
    function reverseKGroup(head: ListNode | null, k: number): ListNode | null {
        let dummy = new ListNode(0, head);
        let pre = dummy;
        // pre->head-> ... ->tail-> next
        while (head != null) {
            let tail = pre;
            for (let i = 0; i < k; ++i) {
                tail = tail.next;
                if (tail == null) {
                    return dummy.next;
                }
            }
            let t = tail.next;
            [head, tail] = reverse(head, tail);
            // set next
            pre.next = head;
            tail.next = t;
            // set new pre and new head
            pre = tail;
            head = t;
        }
        return dummy.next;
    }
    
    function reverse(head: ListNode, tail: ListNode) {
        let cur = head;
        let pre = tail.next;
        // head -> next -> ... -> tail -> pre
        while (pre != tail) {
            let t = cur.next;
            cur.next = pre;
            pre = cur;
            cur = t;
        }
        return [tail, head];
    }
    python
    class Solution:
        def reverseKGroup(self, head: ListNode, k: int) -> ListNode:
            def reverseList(head):
                pre, p = None, head
                while p:
                    q = p.next
                    p.next = pre
                    pre = p
                    p = q
                return pre
    
            dummy = ListNode(next=head)
            pre = cur = dummy
            while cur.next:
                for _ in range(k):
                    cur = cur.next
                    if cur is None:
                        return dummy.next
                t = cur.next
                cur.next = None
                start = pre.next
                pre.next = reverseList(start)
                start.next = t
                pre = start
                cur = pre
            return dummy.next

    方法二:递归

    时间复杂度为 O(n),空间复杂度为 O(logkn),其中 n 是链表的长度。

    ts
    function reverseKGroup(head: ListNode | null, k: number): ListNode | null {
        if (k === 1) {
            return head;
        }
    
        const dummy = new ListNode(0, head);
        let root = dummy;
        while (root != null) {
            let pre = root;
            let cur = root;
    
            let count = 0;
            while (count !== k) {
                count++;
                cur = cur.next;
                if (cur == null) {
                    return dummy.next;
                }
            }
    
            const nextRoot = pre.next;
            pre.next = cur;
    
            let node = nextRoot;
            let next = node.next;
            node.next = cur.next;
            while (node != cur) {
                [next.next, node, next] = [node, next, next.next];
            }
            root = nextRoot;
        }
    
        return dummy.next;
    }

    Released under the MIT License.