1. 程式人生 > >LeetCode筆記——61旋轉連結串列

LeetCode筆記——61旋轉連結串列

題目:

給定一個連結串列,旋轉連結串列,將連結串列每個節點向右移動 個位置,其中 是非負數。

示例 1:

輸入: 1->2->3->4->5->NULL, k = 2
輸出: 4->5->1->2->3->NULL
解釋:
向右旋轉 1 步: 5->1->2->3->4->NULL
向右旋轉 2 步: 4->5->1->2->3->NULL

示例 2:

輸入: 0->1->2->NULL, k = 4
輸出:
2->0->1->NULL 解釋: 向右旋轉 1 步: 2->0->1->NULL 向右旋轉 2 步: 1->2->0->NULL 向右旋轉 3 步: 0->1->2->NULL 向右旋轉 4 步: 2->0->1->NULL

思路:首先先找到需要移動的節點的前一個節點,然後依次將需要移動的節點拿下來再接在連結串列的前端。連結串列好複雜。。。

程式碼:

public class Solution {
    public ListNode rotateRight(ListNode head, int n) {
        if (head == null || n < 1) {
            return head;
        }
        ListNode root = new ListNode(0);
        root.next = head;
        ListNode p = root;
        ListNode q = root;
        int count = 0;
        for (int i = 0; i <=n; i++) {
            p = p.next;
            count++;
            if (p == null) {  //移動的距離比連結串列的長度長
                count--; // 連結串列中除頭結點後資料個數
                n = n % count; // 實際要位置的位數
                // 為重新開始位移做準備
                i = 0; p = head;
            }
        }
        // 找到第一個要交換的結點的前驅
        // q為第一個要交換的結點的前驅
        while (p != null) {
            p = p.next; q = q.next;
        }
        p = q;
        q = root;
        if (p != null && p.next != null) {
            // 有要位移的結點
            ListNode node;
            while (p.next != null) {
                // 摘除結點
                node = p.next;
                p.next = node.next; // 接上結點
                node.next = q.next;
                q.next = node;
                q = node; // 最後一個移動的節點
            }
        }
        return root.next;
    }
}

 

執行最快的程式碼:

思路基本上和上面的程式碼一致,只不過最後連結串列的處理比上面的簡單好理解一些。最後移動節點時是整體進行移動,而不是一個一個地移動。

class Solution {
    /**
     * 前後指標+求餘法
     */
    public ListNode rotateRight(ListNode head, int k) {
        if (head == null || k <= 0) return head;
        ListNode front = head, behind = head;
        int len = 0;//記錄連結串列長度
        //S1. 初始化front指標
        //兩種情況:1. k小於連結串列長度時,直接前進k步;
        //2. k大於連結串列長度時,首先遍歷一邊連結串列,求出連結串列長度len;然後k%=len;
        //同樣再走剩下的k步;最大複雜度是走2N-1。
        //若k<=N;走k步;若N<k<2N-1,走k步;
        //若k>=2N;走k%N+N步;
        while (k-- > 0) {
            front = front.next;//前進一步
            len++;
            if (front == null) {
                k %= len;//降低k是N好幾倍情況的複雜度
                front = head;//從頭開始走
            }
        }
        //S2. front和behind同時前進;front走到最後一個節點;behind走到前一段的最後一個節點
        if(front == head) return head;
        while (front.next != null) {
            front = front.next;
            behind = behind.next;
        }
        //S3. 連線關係處理
        ListNode newHead = behind.next;//旋轉之後的頭節點
        front.next = head;
        behind.next = null;
        return newHead;
    }
}