leetcode騰訊精選練習之旋轉鏈表(四)

旋轉鏈表

題目:

給定一個鏈表,旋轉鏈表,將鏈表每一個節點向右移動 k 個位置,其中 k 是非負數。
示例 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指針

思路:

再說這個題目的解題步驟以前先說說這個題目的理解,就是鏈表倒着數k個結點,而後斷開k+1和k個結點之間的聯接將其分紅兩個鏈表。而後將先後兩個鏈表調換一下位置從新鏈接起來。(固然當k大於鏈表長度的時候須要取模運算)code

1.計算鏈表的長度。
2.定義一個指針pPre指向頭結點,移動k步。
3.定義一個指針pCur指向頭結點,同時向前移動pPre和pCur指針直到pPre遍歷完整個鏈表,此時pCur即爲倒數第k個結點。
4.在第k個結點處斷開鏈表,再將先後兩個鏈表交換順序後從新鏈接起來。
blog

代碼:

ListNode* rotateRight(ListNode* head, int k) {
    if (head == NULL || head->next == NULL)
    {
        return head;
    }
    ListNode* pPre = head;
    int count = 0;
    while (pPre != NULL)
    {
        pPre = pPre->next;
        count++;
    }
    ListNode* pCur = head;
    pPre = head;
    for (int i = 0; i < k % count; i++)
    {
        pPre = pPre->next;
    }
    if (pPre != NULL)
    {
        while (pPre->next != NULL)
        {
            pPre = pPre->next;
            pCur = pCur->next;
        }
        pPre->next = head;
        head = pCur->next;
        pCur->next = NULL;
    }
    return head;
}

改進版:數學

ListNode* rotateRight(ListNode* head, int k) {
    if (head == NULL || k == 0)
    {
        return head;
    }
    int count = 1;
    ListNode* p = head;
    while (p->next)
    {
        count++;
        p = p->next;
    }
    int left = count - k % count;
    p->next = head;
    for (int i = 0; i < left; ++i)
    {
        p = p->next;
    }
    head = p->next;
    p->next = NULL;
    return head;
}

總結:

1.解題的關鍵是如何將題目轉化爲找到倒數第k個結點
2.另一個巧妙的地方是循環向前移動兩個指針的時候判斷的是pPre->next是否爲NULL,這樣能夠將pPre和pCur分別定位到斷開鏈表後的的最後一個結點上,方便斷開的鏈表進行聯接。
3.改進版是我在網上看到別人的思路實現的。首先統計整個鏈表的長度,同時將一個指針指向鏈表的最後一個結點,而後將鏈表首尾聯接起來,組成一個環,而後用數學的方法計算出正着數應該移動left步,而後將指向最後一個結點的指針移動left步,最後在這個位置將鏈表斷開即獲得結果。

有時候思路真的就是一層窗戶紙
List

相關文章
相關標籤/搜索