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

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

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

  • 相关阅读:
    com.opensymphony.xwork2.inject.DependencyException: com.opensymphony.xwork2.inject.ContainerImpl$Mis
    【MVC框架】——View和Controller之间的传值
    &lt;感悟帖&gt;互联网与电子传统行业之经历
    数据挖掘之七种经常使用的方法
    Linux下Java线程具体监控和其dump的分析使用----分析Java性能瓶颈[张振华-Jack]
    mysql 存储引擎的选择你会吗?
    基于新唐M0的XXTEA加密解密算法源码
    TEA encryption with 128bit key
    数据的加密传输——单片机上实现TEA加密解密算法(转)
    keil c51的内部RAM(idata)动态内存管理程序(转)
  • 原文地址:https://www.cnblogs.com/lichen782/p/leetcode_Reverse_Nodes_in_kGroup.html
Copyright © 2011-2022 走看看