單鏈表中k個結點一組進行反轉

原題

  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->5java

題目大意

  給定一個單鏈表,和一個分組數K,每K個結點進行反轉,若是最後的結點數不足K個就保持原來的連接順序不變。node

解題思路

  用一個指針記錄連接好的鏈表的最後一個結點(tail),用一個指針記錄上一次連接好的部分的最後一個結點(head)對未鏈表的結點在head處進行尾插法,插k個元素,再將head移動到tail處,tail從新記錄鏈表的尾結點,直到全部的元素都進行了操做。若是最後的一組元素不足k個,由於進行過尾插法,因此還要進行還原,對最後的head元素進行尾插法就能夠了算法

代碼實現

結點類app

public class ListNode {
    int val;
    ListNode next;

    ListNode(int x) {
        val = x;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

算法實現類this

public class Solution {

    public ListNode reverseKGroup(ListNode head, int k) {

        if (k <= 1) {
            return head;
        }

        ListNode root = new ListNode(0);
        // 分組的頭一個元素的前驅
        ListNode groupHead = root;
        // 當前要處理的結點
        ListNode curr = head;
        // 處理好的鏈表的尾結點
        ListNode groupTail = head;
        // 當前要處理的結點的後繼
        ListNode next;

        // 對每一個組,處理了多少個結點
        int count = 0;


        while (curr != null) {

            // 若是是分組的第一個元素就記錄它
            if (count == 0) {
                groupTail = curr;
            }

            // 記錄處理的元素個數
            count++;
            // 記錄下一個待處理結點
            next = curr.next;
            // 進行尾插法操做
            curr.next = groupHead.next;
            groupHead.next = curr;
            curr = next;

            // 已經處理完了k個結點,分組頭的前驅移動到最後一個連接好的結點
            if (count == k) {
                groupHead = groupTail;
                // 計數器歸零
                count = 0;
            }
        }


        // 說明結點個數不是k的整數倍,將最後不是整數倍的個元素的結點,
        // 再次使用尾插法進行還原
        if (count != 0) {
            curr = groupHead.next;
            groupHead.next = null;

            while (curr != null) {
                next = curr.next;
                curr.next = groupHead.next;
                groupHead.next = curr;
                curr = next;
            }
        }

        return root.next;
    }
}

 

 

問題:spa

以k個元素爲一組,反轉單向鏈表。好比:.net

輸入: 1->2->3->4->5->6->7->8->null and k = 3指針

輸出:3->2->1->6->5->4->8->7->null. rest

分析:code

咱們能夠把整個鏈表分紅多個長度爲 k  的子鏈表, 而後,咱們再反轉每個子鏈表(遞歸)。問題的關鍵是咱們須要把每一個子鏈表再鏈接起來。因此,對每個子鏈表操做之後,咱們須要返回該子鏈表的頭(head),而後,咱們設置前一個子鏈表的最後一個node,把它的next 設置成下一個鏈表返回的頭(head),這樣,全部的子鏈表就鏈接起來了。

 

[java] view plain copy

 

  1. public static Node reverse (Node head, int k) {  
  2.     Node current = head;  
  3.     Node next = null;  
  4.     Node prev = null;  
  5.     int count = 0;     
  6.       
  7.     /*reverse first k nodes of the linked list */  
  8.     while (current != null && count < k) {  
  9.        next  = current.next;  
  10.        current.next = prev;  
  11.        prev = current;  
  12.        current = next;  
  13.        count++;  
  14.     }  
  15.    
  16.     /* next is now a pointer to (k+1)th node 
  17.        Recursively call for the list starting from current. 
  18.        And make rest of the list as next of first node */  
  19.     if(next !=  null) {  
  20.         head.next = reverse(next, k);   
  21.     }  
  22.    
  23.     /* prev is new head of the input list */  
  24.     return prev;  
  25. }  

 

這個問題也可使用非遞歸的方法,基本上問題的處理方式和遞歸是同樣的,可是,非遞歸的方式要稍微複雜一點,由於每次對子鏈表反轉之後,咱們須要更新前一個子鏈表最後一個node 的next 值。代碼以下:

 

[java] view plain copy

 

  1. class Node {  
  2.      int val;  
  3.      Node next;  
  4.      Node(int x) {  
  5.          val = x;  
  6.          next = null;  
  7.      }  
  8. }  
  9.   
  10. public class Solution {  
  11.       
  12.     public static void main(String[] args) {  
  13.         Solution s = new Solution();  
  14.           
  15.         Node n1 = new Node(1);  
  16.         Node n2 = new Node(2);  
  17.         Node n3 = new Node(3);  
  18.         Node n4 = new Node(4);  
  19.         Node n5 = new Node(5);  
  20.           
  21.         n1.next = n2;  
  22.         n2.next = n3;  
  23.         n3.next = n4;  
  24.         n4.next = n5;  
  25.           
  26.         Node head = s.ReverseInGroups(n1, 2);  
  27.         while (head != null) {  
  28.             System.out.println(head.val);  
  29.             head = head.next;  
  30.         }  
  31.     }  
  32.     public Node ReverseInGroups(Node current, int k) {  
  33.         if (current == null || current.next == null ) return current;  
  34.         //store the new head of the list  
  35.         Node newHead = null;  
  36.           
  37.         //store the last node in the sub-list,   
  38.         //we will update its next value when finishing  
  39.         //reversing the next sub-list  
  40.         Node previousGroupTail = null;  
  41.         int count = 1; //used to track the first sub-list  
  42.         while (current != null) {     
  43.             // the actual tail in the sub-list  
  44.             Node groupTail = current;  
  45.             //reverse  
  46.             Node prev = null;  
  47.             Node next = null;  
  48.             for (int i = 1; i <= k && current != null; i++) {  
  49.                 next = current.next;  
  50.                 current.next = prev;  
  51.                 prev = current;  
  52.                 current = next;  
  53.             }  
  54.             // get the new head of the whole list  
  55.             if (count == 1) {  
  56.                 newHead = prev;  
  57.                 count++;  
  58.             }  
  59.             // update the next value of the last node in  
  60.             // each sub-list  
  61.             if (previousGroupTail != null) {  
  62.                 previousGroupTail.next = prev;  
  63.             }  
  64.             previousGroupTail = groupTail;  
  65.         }  
  66.         return newHead;  
  67.     }  
相關文章
相關標籤/搜索