zoukankan      html  css  js  c++  java
  • 25. Reverse Nodes in k-Group

    题目:

    Given a linked list, reverse the nodes of a linked list k at a time and return its modified list.

    If the number of nodes is not a multiple of k then left-out nodes in the end should remain as it is.

    You may not alter the values in the nodes, only nodes itself may be changed.

    Only constant memory is allowed.

    For example,
    Given this linked list: 1->2->3->4->5

    For k = 2, you should return: 2->1->4->3->5

    For k = 3, you should return: 3->2->1->4->5

    链接:

    题解:

    题目要求constant memory,所以一般要用iterative解法或者尾递归。

    先来看递归。思路很简单,先找到第 k 和 k + 1节点,对k + 1节点进行递归,之后再用reverse list的方法对前k个节点进行reverse即可

    Time Complexity - O(n), Space Complexity - O(n),  虽然能ac但是Space Complexity不满足题意。代码比较sloppy,以后要继续refactor。

    public class Solution {
        public ListNode reverseKGroup(ListNode head, int k) {
            if(head == null || head.next == null || k <= 1)
                return head;        
            ListNode kthNode = head;
            int count = 1;
            
            while(count < k) {
                if(kthNode == null)
                    return head;
                kthNode = kthNode.next;
                count++;
            }
               
            if(kthNode == null)
                return head;
            ListNode kplusoneNode = kthNode.next;        
            kthNode.next = null;        
            ListNode newHead = reverse(head);
            head.next = reverseKGroup(kplusoneNode, k);
            return newHead;
        }
        
        private ListNode reverse(ListNode head) {
            if(head == null || head.next == null)
                return head;
            ListNode dummy = new ListNode(-1);
            
            while(head != null) {
                ListNode tmp = head.next;
                head.next = dummy.next;
                dummy.next = head;
                head = tmp;
            }
            
            return dummy.next;
        }
    }

    接下来看迭代。思路和reverse linked list II 很像, 我们需要dummy,preHead,head, tail,postTail几个节点。有了这些节点以后,就可以做一个local的reverse K-group node运算,reverse之后的结果再和之前的preHead以及postTail连接起来,最后更新preHead = head; head = postTail; 就可以继续下面操作了。节点之间的转换还可以再继续简化,有时间的话还要继续refactor,也可以把reverse这一部分直接写到主要的方法体里,用 count来判定reverse到哪一个节点。

    Time Complexity - O(n), Space Complexity - O(1)。

    /**
     * Definition for singly-linked list.
     * public class ListNode {
     *     int val;
     *     ListNode next;
     *     ListNode(int x) { val = x; }
     * }
     */
    public class Solution {
        public ListNode reverseKGroup(ListNode head, int k) {
            if(head == null || head.next == null || k == 1)
                return head;
            ListNode dummy = new ListNode(-1);
            dummy.next = head;
            ListNode preHead = dummy, tail, postTail;       //we need preHead, head, tail and postTail
            
            while(head != null) {
                tail = head;
                int count = 1; 
                
                while(count < k) {            //find tail 
                   if(tail == null)
                      return dummy.next;
                   tail = tail.next;
                   count++;
                }
                
                if(tail == null)
                    return dummy.next;
                    
                postTail = tail.next;
                tail.next = null;
                preHead.next = reverse(head);
                head.next = postTail;
                preHead = head;
                head = head.next;
            }
            
            return dummy.next;
        }
        
         private ListNode reverse(ListNode head) {
            if(head == null || head.next == null)
                return head;
            ListNode dummy = new ListNode(-1);
            
            while(head != null) {
                ListNode tmp = head.next;
                head.next = dummy.next;
                dummy.next = head;
                head = tmp;
            }
            
            return dummy.next;
        }
    }

    这道题最好和前面的节点翻转题目结合起来做,顺序如下:

    1) Reverse Linked List

    2) Reverse Linked List II

    3) Swap Node in Pairs

    4) Reverse Linked List in K-Group

    二刷:

    分成几步思考,感觉难度不是那么大。另外Space Complexity其实等于O(k),假如k是比较小的常数那么也可以理解为Constant Space,否则还要把reverse函数写回去到函数体力。

    Java:

    /**
     * Definition for singly-linked list.
     * public class ListNode {
     *     int val;
     *     ListNode next;
     *     ListNode(int x) { val = x; }
     * }
     */
    public class Solution {
        public ListNode reverseKGroup(ListNode head, int k) {
            if (head == null || head.next == null || k <= 1) {
                return head;
            }
            ListNode dummy = new ListNode(-1);
            dummy.next = head;
            ListNode preHead = dummy, tail = dummy, postTail = dummy;
            int count = 0;
            while (tail != null) {
                if (count == k) {
                    count = 0;
                    postTail = tail.next;
                    tail.next = null;
                    preHead.next = reverse(head);
                    head.next = postTail;
                    preHead = head;
                    tail = head;
                    head = head.next;
                }
                tail = tail.next;
                count++;
            }
            return dummy.next;
        }
        
        private ListNode reverse(ListNode head) {
            if (head == null || head.next == null) {
                return head;
            }
            ListNode dummy = new ListNode(-1);
            while (head != null) {
                ListNode tmp = head.next;
                head.next = dummy.next;
                dummy.next = head;
                head = tmp;
            }
            return dummy.next;
        }
    }

    纯的constant space Complexity:

    /**
     * Definition for singly-linked list.
     * public class ListNode {
     *     int val;
     *     ListNode next;
     *     ListNode(int x) { val = x; }
     * }
     */
    public class Solution {
        public ListNode reverseKGroup(ListNode head, int k) {
            if (head == null || head.next == null || k <= 1) {
                return head;
            }
            ListNode dummy = new ListNode(-1);
            dummy.next = head;
            ListNode preHead = dummy, tail = dummy, postTail, tmp;
            int count = 0;
            while (tail != null) {
                if (count == k) {
                    count = 0;
                    postTail = tail.next;
                    tail.next = null;
                    preHead.next = null;
                    tail = head;               //reuse "tail"
                    while (tail != null) {     //reverse head to original tail
                        tmp = tail.next;
                        tail.next = preHead.next;
                        preHead.next = tail;
                        tail = tmp;
                    }
                    head.next = postTail;
                    preHead = head;
                    tail = preHead;
                    head = head.next;
                }
                tail = tail.next;
                count++;
            }
            return dummy.next;
        }
    }

    三刷:

    Java:

    /**
     * Definition for singly-linked list.
     * public class ListNode {
     *     int val;
     *     ListNode next;
     *     ListNode(int x) { val = x; }
     * }
     */
    public class Solution {
        public ListNode reverseKGroup(ListNode head, int k) {
            if (head == null || head.next == null || k <= 1) return head;
            ListNode dummy = new ListNode(-1);
            dummy.next = head;
            ListNode curr = dummy, preHead = dummy, postTail = null, tmp = null;
            int count = 0;
            while (curr.next != null) {
                curr = curr.next;
                count++;
                if (count == k) {
                    postTail = curr.next;
                    curr.next = null;
                    preHead.next = null;
                    curr = head;
                    while (curr != null) {
                        tmp = curr.next;
                        curr.next = preHead.next;
                        preHead.next = curr;
                        curr = tmp;
                    }
                    head.next = postTail;
                    preHead = head;
                    curr = head;
                    head = postTail;
                    count = 0;
                }
            }
            return dummy.next;
        }
    }

    Reference:

    https://leetcode.com/discuss/21301/short-but-recursive-java-code-with-comments

  • 相关阅读:
    Newtonsoft.Json 把对象转换成json字符串
    分页总页数计算方法 所有分页通用
    好用的Markdown编辑器一览 readme.md 编辑查看
    jquery bootgrid 一个很好的 数据控件,可用于任何语言
    史上最详细“截图”搭建Hexo博客——For Windows
    史上最详细“截图”搭建Hexo博客并部署到Github
    正则表达式30分钟入门教程
    [前端插件]为自己的博客增加打赏功能
    css浮动
    MetaWeblog API调用
  • 原文地址:https://www.cnblogs.com/yrbbest/p/4434866.html
Copyright © 2011-2022 走看看