LeetCode 25. Reverse Nodes in k-Group

栏目: 数据库 · 发布时间: 5年前

内容简介:给定一个链表,k个一组反转链表。

本文为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》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

深入理解C++11

深入理解C++11

Michael Wong、IBM XL编译器中国开发团队 / 机械工业出版社 / 2013-6 / 69.00元

《深入理解C++11:C++11新特性解析与应用》内容简介:国内首本全面深入解读C++11新标准的专著,由C++标准委员会代表和IBM XL编译器中国开发团队共同撰写。不仅详细阐述了C++11标准的设计原则,而且系统地讲解了C++11新标准中的所有新语言特性、新标准库特性、对原有特性的改进,以及如何应用所有这些新特性。 《深入理解C++11:C++11新特性解析与应用》一共8章:第1章从设计......一起来看看 《深入理解C++11》 这本书的介绍吧!

URL 编码/解码
URL 编码/解码

URL 编码/解码

SHA 加密
SHA 加密

SHA 加密工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具