LeetCode 25. Reverse Nodes in k-Group

本文为LeetCode 25. Reverse Nodes in k-Group的题解。

题意

给定一个链表,k个一组反转链表。

k 是一个正数,且小于链表长度。如果按照k个一组,最后剩下的不组k,则不反转剩下的元素。

例子:

对于链表: 1->2->3->4->5

k = 2, 应返回: 2->1->4->3->5

k = 3, 应返回: 3->2->1->4->5

注意:

  • 只允许O(1)的空间复杂度。
  • 不可以改变节点的值。

题解

这个题目麻烦的地方在于边界情况太多。但简单而言,可按照如下处理:

  1. k个一组分组,满k个为完整组,不满k个为不完整组
  2. 对于完整组,反转,然后接到结果中
  3. 对于不完整组,直接接到结果中

代码

/**
* https://www.robberphex.com/reverse-nodes-in-k-group/
* Runtime: 1 ms, faster than 41.14% of Java online submissions for Reverse Nodes in k-Group.
* Memory Usage: 38.5 MB, less than 24.80% of Java online submissions for Reverse Nodes in k-Group.
*/
class Solution {
public ListNode reverseKGroup(ListNode head, int k) {
int length = 0;

    // 存储返回结果的第一个和最后一个节点
    ListNode totalHead = null;
    ListNode totalTail = null;
    // 存储当前组中第一个和最后一个节点
    ListNode segHead = null;
    ListNode segTail = null;
    // 遍历
    while (head != null) {
        // 将当前元素放到组中队首
        // 即反转了顺序
        ListNode tmp = head.next;
        head.next = segHead;
        segHead = head;

        // group首
        if (length % k == 0) {
            segTail = head;
        }

        // group 尾
        if (length % k == k - 1) {
            // 如果结果的head没有出现,则设置
            if (totalHead == null) {
                totalHead = segHead;
            }
            // 如果有队列尾,则将当前组添加到尾部
            if (totalTail != null) {
                totalTail.next = segHead;
            }
            totalTail = segTail;
            // 开始新的组
            segHead = null;
        }

        head = tmp;
        length++;
    }

    // 如果还剩下不完整的组,我们需要再次反转
    // 将其转换为正序
    if (length % k != 0) {
        head = segHead;
        segHead = null;
        while (head != null) {
            ListNode tmp = head.next;
            head.next = segHead;
            segHead = head;
            head = tmp;
        }
    }
    // 将不完整组添加到结果中
    if (totalTail != null) {
        totalTail.next = segHead;
    } else {
        totalHead = segHead;
    }
    return totalHead;
}

public static void main(String\[\] args) {
    ListNode head = new ListNode(1);
    head.next = new ListNode(2);
    head.next.next = new ListNode(3);
    head.next.next.next = new ListNode(4);
    head.next.next.next.next = new ListNode(5);
    ListNode res = new Solution().reverseKGroup(head, 2);

    while (res != null) {
        System.out.print(res.val);
        System.out.print(", ");
        res = res.next;
    }
    System.out.println();
    // 输出 2, 1, 4, 3, 5,
}

}

备注

看了下,还有更快的0ms的解法:

/**
* https://www.robberphex.com/reverse-nodes-in-k-group/
* Runtime: 0 ms, faster than 100.00% of Java online submissions for Reverse Nodes in k-Group.
* Memory Usage: 38.5 MB, less than 24.52% of Java online submissions for Reverse Nodes in k-Group.
*/
class Solution {
public ListNode reverseKGroup(ListNode head, int k) {
ListNode cur = head;
int cnt = 0;
ListNode prev = null;
while (cnt < k) {
if (cur == null) {
// 当前不足k个,直接返回
return head;
}
prev = cur;
cur = cur.next;
cnt++;
}
// 将k个从原链表中切出来
prev.next = null;

    // 反转原链表,这时prev是头,head是尾了
    reverse(head);

    // 继续递归分剩下的
    head.next = reverseKGroup(cur, k);

    return prev;
}

private ListNode reverse(ListNode head) {
    if (head == null || head.next == null) {
        return head;
    }
    ListNode newHead = reverse(head.next);
    head.next.next = head;
    head.next = null;
    return newHead;
}

public static void main(String\[\] args) {
    ListNode head = new ListNode(1);
    head.next = new ListNode(2);
    head.next.next = new ListNode(3);
    head.next.next.next = new ListNode(4);
    head.next.next.next.next = new ListNode(5);
    ListNode res = new Solution().reverseKGroup(head, 2);

    while (res != null) {
        System.out.print(res.val);
        System.out.print(", ");
        res = res.next;
    }
    System.out.println();
    // 输出 2, 1, 4, 3, 5,
}

}

但是这个解法根本不符合要求啊,reverse空间复杂度O(n),reverseKGroup空间复杂度O(n/k)+O(n)≈O(n)。希望LeetCode能够再完善下测试数据集。

LeetCode 25. Reverse Nodes in k-Group

https://www.robberphex.com/reverse-nodes-in-k-group/

作者

Robert Lu

发布于

2019-07-01

许可协议

评论