zoukankan      html  css  js  c++  java
  • LeetCode 笔记系列六 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

    这个题目花了蛮长时间,主要是没搞清楚逆转一个链表的关系。弄了半天。其实是蛮简单和经典的题目。

    解法一:比较挫的解法。要判断很多分支,所以容易出错。先放在这里当反面教材。

     1 public static ListNode reverseKGroup(ListNode head, int k) {
     2         // Start typing your Java solution below
     3         // DO NOT write main() function
     4         ListNode firstGHead = head;
     5         int idx = 0;
     6         ListNode pp = null;
     7         while(head != null) {
     8             ListNode c = head;
     9             if(k <= 1 || c == null)return firstGHead;
    10             for(int i = 0; i < k - 1&& c != null;i++) {
    11                 c = c.next;
    12             }
    13             if(c == null) break; 
    14             c = head;//save original head
    15             int i = k - 1;
    16             ListNode p = head;
    17             ListNode pn = p.next;
    18             ListNode lastEnd = pp;
    19             while(i > 0){
    20                 p = head;
    21                 head = head.next;
    22                 pn = p.next;
    23                 pp = lastEnd;
    24                 int swap = 0;
    25                 while(swap < i){
    26                     p.next = pn.next;
    27                     pn.next = p;
    28                     if(pp != null)
    29                         pp.next = pn;
    30                     pp = pn;
    31                     pn= p.next;
    32                     swap++;
    33                 }
    34                 i--;
    35             }
    36             if(idx++ == 0) firstGHead = head;
    37             head = c.next;
    38             pp = c;
    39         }
    40         return firstGHead;
    View Code

    逆转那部分惨不忍睹啊。。。虽然过了leetcode,但是很不simple。还有,如果写成递归leetcode是不让你过的。

    解法二:比较好的解法,又是leetcode讨论组的人做的。首先,搞清楚怎么逆转一个单链表。其实O(n)就可以了。第一个肯定是last one。然后我们每遍历到一个node,就把它放到最链表的首位,最后一个么,最后就成为第一个了。下面是一个简单逆转链表的程序。

     1 ListNode dummy = new ListNode(0);
     2         dummy.next = head;
     3         ListNode pre = dummy;
     4         ListNode cur = head.next;
     5         ListNode last = head;
     6         while(cur != null){
     7             last.next = cur.next;
     8             cur.next = pre.next;
     9             pre.next = cur;
    10             cur = last.next;
    11         }
    12         head = dummy.next;
    reverse a linked list with a head node

    因为有“放到链表首位”的操作,我们需要一个dummy的头节点,遇到的新节点我们simply state: pre.next = cur; 保持一个invariant就是last节点始终在最后(cur的前面一个)

    然后我们有如下方法:

    /**
         * Reverse a link list between pre and next exclusively
         * an example:
         * a linked list:
         * 0->1->2->3->4->5->6
         * |           |   
         * pre        next
         * after call pre = reverse(pre, next)
         * 
         * 0->3->2->1->4->5->6
         *          |  |
         *          pre next
         * @param pre 
         * @param next
         * @return the reversed list's last node, which is the precedence of parameter next
         */
        private static ListNode reverse(ListNode pre, ListNode next){
            ListNode last = pre.next;//where first will be doomed "last"
            ListNode cur = last.next;
            while(cur != next){
                last.next = cur.next;
                cur.next = pre.next;
                pre.next = cur;
                cur = last.next;
            }
            return last;
        }
    reverse range

    就是区间的reverse。因为题目要求的是k group逆转嘛。注意人返回的是最后一个(last)节点,这样下一个k-group就可以用上了。牛人的想法真是周到体贴~~。主方法里面,遍历的过程中每次都计数,每次到达k个节点,就可以使用pre和head.next调用上面的方法逆转了。给跪了。

     1 public static ListNode reverseKGroup2(ListNode head, int k) {
     2         if(head == null || k == 1) return head;
     3         ListNode dummy = new ListNode(0);
     4         dummy.next = head;
     5         ListNode pre = dummy;
     6         int i = 0;
     7         while(head != null){
     8             i++;
     9             if(i % k ==0){
    10                 pre = reverse(pre, head.next);
    11                 head = pre.next;
    12             }else {
    13                 head = head.next;
    14             }
    15         }
    16         return dummy.next;
    17     }
    reverseKGroup

    通过这道题,我们学会了:

    有效的算法是简洁的!简洁的!!简洁的!!!

  • 相关阅读:
    JqueryQrcode生成二维码不支持中文的解决办法
    [转载]浅析海量用户的分布式系统设计
    [转载]大型网站应用中 MySQL 的架构演变史
    CSS3变形记(上):千变万化的Div
    JavaScript进阶之路——认识和使用Promise,重构你的Js代码
    Visual Studio Code预览版Ver 0.3.0试用体验
    Apache Spark 2.3.0 正式发布
    Apache Spark 2.2.0 新特性详细介绍
    Apache Spark 2.2.0 正式发布
    Spark 论文篇-论文中英语单词集
  • 原文地址:https://www.cnblogs.com/lichen782/p/leetcode_Reverse_Nodes_in_kGroup.html
Copyright © 2011-2022 走看看