1. 程式人生 > >leetcode:25. Reverse Nodes in k-Group

leetcode: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

Subscribe to see which companies asked this question

我的思路:將連結串列拆成k個連結串列,每個連結串列兩個元素之間在原連結串列的距離為k,然後利用歸併的思想將這k個連結串列歸併,歸併的順序為拆開的逆序。例如當連結串列為1 2 3 4 5 6 7 8 9,k為3時,三個連結串列分別為1 4 7,2 5 8,3 6 9;歸併的順序為3 2 1 6 5 4 9 8 7。思路不麻煩,實現起來也不容易。

程式碼如下:

    //利用k路歸併的思想
    public ListNode reverseKGroup(ListNode head, int k) {

    	if(k==1){
    		return head;
    	}
    	
        if(!canAssign(head,k)){
            return head;
        }

        ListNode[] kRoad = new ListNode[k];     //儲存k個子連結串列的頭結點
        ListNode[] kLast = new ListNode[k];     //儲存k個子連結串列的尾節點
        ListNode p = head;

        for(int i=0;i<k;i++){                   //初始化子連結串列
            kRoad[i] = p;
            kLast[i] = p;
            p = p.next;
        }

        while(canAssign(p,k)){ 
            for(int i=0;i<k;i++){               //拆鏈,更新尾節點
                kLast[i].next = p;
                kLast[i] = p;
                p = p.next;                     //注意,這裡p儲存了最後不滿k個節點的剩餘節點
            }
        }
        for(int i=0;i<k;i++){                  //將k個子鏈的最後節點置為null。
            kLast[i].next = null;
        }

        ListNode lastNode = new ListNode(1);   //執行歸併操作,lastNode儲存已經連起來的最後一個節點
        ListNode preHead = lastNode;
        ListNode firstList = kRoad[k-1];       //這個節點只用來標識迴圈結束

        while (firstList!=null){
            firstList = firstList.next;

            for(int i=k-1;i>=0;i--){
                lastNode.next = kRoad[i];
                lastNode = kRoad[i];
                kRoad[i] = kRoad[i].next;      //更新kRoad連結串列,已經儲存的就不需要了
            }
            
        }

        while (p!=null){
            lastNode.next = p;
            lastNode = p;
            p = p.next;
        }

        return preHead.next;
    }

    //檢查是否還有至少k個節點
    public boolean canAssign(ListNode p,int k){
        int i=0;
        while(i<=k && p!=null){
            p = p.next;
            i++;
        }
        if(i<k){
            return false;
        }
        return true;
    }