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

  • 相关阅读:
    kafka参数解析+启动参数解析
    flume参数解析+启动参数解析
    flume+flume+kafka消息传递+storm消费
    C++快速读取大文件
    阿里云ecs : Couldn't connect to host, port: smtp.aliyun.com, 25; timeout -1;
    对渲染相关操作封装的类库
    51nod-1134 最长递增子序列,用线段树将N^2的dp降到NlogN
    51nod-1503 猪和回文
    51nod1073-约瑟夫环,递归。
    算法基础题
  • 原文地址:https://www.cnblogs.com/yrbbest/p/4434866.html
Copyright © 2011-2022 走看看