• LeetCode: Reverse Nodes in k-Group 解题报告


    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
     
     
    SOLUTION 1
    用递归实现,逐层进行反转。遇到最后一个如果个数不为k,再反转一次即可。
     1 /*
     2     SOLUTION 2: A better rec version.
     3     */
     4     public ListNode reverseKGroup2(ListNode head, int k) {
     5         if (head == null) {
     6             return null;
     7         }        
     8         
     9         return rec2(head, k);
    10     }
    11     
    12     public ListNode rec2(ListNode head, int k) {
    13         if (head == null) {
    14             return null;
    15         }
    16         
    17         ListNode dummy = new ListNode(0);
    18         
    19         ListNode cur = head;
    20         int cnt = 0;
    21         while (cur != null) {
    22             ListNode tmp = cur.next;
    23             cur.next = dummy.next;
    24             dummy.next = cur;
    25             
    26             cur = tmp;
    27             
    28             cnt++;
    29             
    30             // reverse a k group.
    31             if (cnt == k) {
    32                 // BUG 1: 
    33                 head.next = rec2(tmp, k);
    34                 return dummy.next;
    35             }
    36         }
    37         
    38         // we don't have k nodes.
    39         if (cnt != k) {
    40             cur = dummy.next;
    41             dummy.next = null;
    42             
    43             // reverse again.
    44             while (cur != null) {
    45                 ListNode tmp = cur.next;
    46                 cur.next = dummy.next;
    47                 dummy.next = cur;
    48                 
    49                 cur = tmp;
    50             }
    51         }
    52         
    53         return dummy.next;
    54     }
    View Code

    SOLUTION 2

    另一个思路的递归:

    先查看有没有k个node,如果有,切开2个链表,反转当前链表,并且使用递归处理下一个section,最后再把2者连接起来即可。

     1 public ListNode reverseKGroup1(ListNode head, int k) {
     2         if (head == null) {
     3             return null;
     4         }        
     5         
     6         return rec(head, k);
     7     }
     8     
     9     // Solution 1: Recursion.
    10     public ListNode rec(ListNode head, int k) {
    11         // Reverse k and link to the next section.
    12         ListNode dummy = new ListNode(0);
    13         dummy.next = head;
    14         
    15         // find the tail node of the section. If not find, just return.
    16         int cnt = k;
    17         ListNode tail = dummy;
    18         while (cnt > 0 && tail != null) {
    19             cnt--;
    20             tail = tail.next;
    21         }
    22         
    23         // We don't have k nodes to revers.
    24         // bug 1: we should judge that if tail == null to avoid the overflow.
    25         if (tail == null) {
    26             return head;
    27         }
    28         
    29         // cut the 2 list.
    30         ListNode next = tail.next;
    31         tail.next = null;
    32         
    33         // reverse the first list.
    34         ListNode newHead = reverse(head);
    35         
    36         // reverse the next section.
    37         next = rec(next, k);
    38         
    39         // link the 2 sections.
    40         head.next = next;
    41         
    42         return newHead;
    43     }
    44     
    45     public ListNode reverse(ListNode head) {
    46         ListNode dummy = new ListNode(0);
    47         while (head != null) {
    48             ListNode tmp = head.next;
    49             head.next = dummy.next;
    50             dummy.next = head;
    51             
    52             head = tmp;
    53         }
    54         
    55         return dummy.next;
    56     }
    View Code

    SOLUTION 3

    使用一个专用的反转函数来进行反转,从头到尾遍历,遍历到K的时候,使用Pre-Next指针的方式进行反转。这个方法比递归更棒。

    要特别注意的是:

    reverseSection 函数中,while 循环的终止条件不是cur != null,而是cur != next。这一点要特别注意,否则很容易造成死循环!

    // BUG: Severe. if we use cur != null here, we will cause very serious loop error.
    while (cur != next) {
       ...
    }

     1 /*
     2     SOLUTION 3: A Iteration version.
     3     */
     4     public ListNode reverseKGroup(ListNode head, int k) {
     5         if (head == null) {
     6             return null;
     7         }        
     8         
     9         ListNode dummy = new ListNode(0);
    10         dummy.next = head;
    11         
    12         ListNode pre = dummy;
    13         ListNode cur = pre.next;
    14         
    15         int cnt = 0;
    16         while (cur != null) {
    17             cnt++;
    18             cur = cur.next;
    19             
    20             if (cnt == k) {
    21                 cnt = 0;
    22                 pre = reverseSection(pre, cur);
    23                 cur = pre.next;
    24             }
    25         }
    26         
    27         return dummy.next;
    28     }
    29     
    30     
    31     /**
    32      * Reverse a link list between pre and next exclusively
    33      * an example:
    34      * a linked list:
    35      * 0->1->2->3->4->5->6
    36      * |           |   
    37      * pre        next
    38      * after call pre = reverse(pre, next)
    39      * 
    40      * 0->3->2->1->4->5->6
    41      *          |  |
    42      *          pre next
    43      * @param pre 
    44      * @param next
    45      * @return the reversed list's last node, which is the precedence of parameter next
    46      */
    47     private static ListNode reverseSection(ListNode pre, ListNode next){
    48         ListNode cur = pre.next;
    49         
    50         // record the new tail.
    51         ListNode tail = cur;
    52         
    53         // BUG: Severe. if we use cur != null here, we will cause very serious loop error.
    54         while (cur != next) {
    55             ListNode tmp = cur.next;
    56             cur.next = pre.next;
    57             pre.next = cur;
    58             cur = tmp;
    59         }
    60         
    61         tail.next = next;
    62         return tail;
    63     }
    View Code

    GITHUB:

    1. 主页君的GitHub代码

    2. 2014.1227 Redo:

    https://github.com/yuzhangcmu/LeetCode_algorithm/blob/master/list/ReverseKGroup_1227_2014.java

    ref: http://www.cnblogs.com/lichen782/p/leetcode_Reverse_Nodes_in_kGroup.html

  • 相关阅读:
    计数器应用-数据清洗案例
    Map Join实战案例
    Reduce Join实战案例
    自定义OutputFormat代码实现
    Golang的序列化-RPC和GRPC
    jetty服务器的安装和部署、新增到开机启动服务
    myeclipse不编译解决方法
    MyEclipse从数据库反向生成实体类之Hibernate方式 反向工程
    MyEclipse自动生成hibernate实体类和配置文件攻略
    eclipse从数据库逆向生成Hibernate实体类
  • 原文地址:https://www.cnblogs.com/yuzhangcmu/p/4037039.html
Copyright © 2020-2023  润新知