Leetcode92 反轉鏈表(反轉指定位置的鏈表)

反轉從位置 m 到 n 的鏈表。請使用一趟掃描完成反轉。
說明:
1 ≤ m ≤ n ≤ 鏈表長度。
示例:
輸入: 1->2->3->4->5->NULL, m = 2, n = 4
輸出: 1->4->3->2->5->NULL

對於鏈表的問題,根據以往的經驗一般都是要建一個dummy node,連上原鏈表的頭結點,這樣的話就算頭結點變動了,我們還可以通過dummy->next來獲得新鏈表的頭結點。這道題的要求是隻通過一次遍歷完成,就拿題目中的例子來說,變換的是2,3,4這三個點,我們需要找到第一個開始變換結點的前一個結點,只要讓pre向後走m-1步即可,爲啥要減1呢,因爲題目中是從1開始計數的,這裏只走了1步,就是結點1,用pre指向它。萬一是結點1開始變換的怎麼辦,這就是我們爲啥要用dummy結點了,pre也可以指向dummy結點。然後就要開始交換了,由於一次只能交換兩個結點,所以我們按如下的交換順序:

1 -> 2 -> 3 -> 4 -> 5 -> NULL

1 -> 3 -> 2 -> 4 -> 5 -> NULL

1 -> 4 -> 3 -> 2 -> 5 -> NULL

我們可以看出來,總共需要n-m步即可,第一步是將結點3放到結點1的後面,第二步將結點4放到結點1的後面。這是很有規律的操作,那麼我們就說一個就行了,比如剛開始,pre指向結點1,cur指向結點2,然後我們建立一個臨時的結點t,指向結點3(注意我們用臨時變量保存某個結點就是爲了首先斷開該結點和前面結點之間的聯繫,這可以當作一個規律記下來),然後我們斷開結點2和結點3,將結點2的next連到結點4上,也就是 cur->next = t->next,再把結點3連到結點1的後面結點(即結點2)的前面,即 t->next = pre->next,最後再將原來的結點1和結點2的連接斷開,將結點1連到結點3,即 pre->next = t。這樣我們就完成了將結點3取出,加入結點1的後方。第二步將結點4取出,加入結點1的後方,也是同樣的操作,

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* reverseBetween(ListNode* head, int m, int n) {
        ListNode* dummy=new ListNode(-1);
        ListNode* pre=dummy;
        dummy->next=head;
        
        for(int i=0;i<m-1;i++)
            pre=pre->next;
        ListNode* cur=pre->next;
        for(int i=m;i<n;i++){
            ListNode* t=cur->next;
            cur->next=t->next;
            t->next=pre->next;
            pre->next=t;
        }
        return dummy->next;
    }
};

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章