1. 程式人生 > >【C++】“反轉連結串列”相關的題目

【C++】“反轉連結串列”相關的題目

1.反轉連結串列:定義一個函式,輸入一個連結串列的頭節點,反轉該連結串列並輸出反轉後連結串列的頭節點。

(1)這道題是經典的題目了,用迭代的方式解決也是很容易的,程式碼量也不大。分享一個我個人做題的方式,我會先在題目開頭寫註釋,理清我結題的思路,然後寫程式碼就很容易了。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        //首先需要判斷特殊情況
        //需要三個指標實現,先記錄當前節點的下一個節點,然後把當前節點的後繼節點變成前一個節點,然後把當前節點變成前一個節點,然後把下一個節點變成當前節點往後迴圈,最後要注意連結串列的頭結點邊到最後了
        //開始擼
        if(head == nullptr || head->next == nullptr)
            return head;
        ListNode* pPre = nullptr;
        ListNode* pCur = head;
        ListNode* pNext = nullptr;
        while(pCur != nullptr)
        {
            pNext = pCur->next;
            pCur->next = pPre;
            pPre = pCur;
            pCur = pNext;
        }return pPre;

    }
};

(2)遞迴解法:簡直是優雅

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        //使用遞迴的方式進行反轉,遞迴反轉連結串列程式碼太簡潔和優雅了,但是要注意基線條件,不能無限迴圈,使用遞迴的核心:不要跳到遞迴裡去!
        if(head == nullptr || head->next == nullptr)
            return head;
        ListNode* last = reverseList(head->next);
        head->next->next = head;
        head->next = nullptr;
        return last;
    }
};

2.反轉連結串列II:

反轉從位置 m 到 n 的連結串列。請使用一趟掃描完成反轉。

說明:
1 ≤ m ≤ n ≤ 連結串列長度。

(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) {
        //按照題意,時間複雜度為O(n)
        //可以使用迭代和遞迴兩種方式進行,時間複雜度都是O(n),但是遞迴的空間複雜度為O(n),而迭代為O(1)
        
        //遞迴解法
        if(m == 1)
            return reverseN(head, n);
        head->next = reverseBetween(head->next, m-1, n-1);
        return head;  
    }
    ListNode* successor = nullptr;
    ListNode* reverseN(ListNode* head, int n)
    {
        if(n==1)
        {
            successor = head->next;
            return head;
        }
        ListNode* last = reverseN(head->next, n-1);
        head->next->next = head;
        head->next = successor;
        return last;
    }

(2)迭代實現

/**
 * 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) {
        //按照題意,時間複雜度為O(n)
        //可以使用迭代和遞迴兩種方式進行,時間複雜度都是O(n),但是遞迴的空間複雜度為O(n),而迭代為O(1)
        
        //迭代解法
        ListNode* pCur = head;
        ListNode* pPre = nullptr;
        ListNode* pNext = nullptr;
        ListNode* pPreM = nullptr;
        ListNode* pM = nullptr;
        for(int i=0;i<m-1;i++)
        {
            pPreM = pCur;
            pCur = pCur->next;
        }
        pM = pCur;
        for(int j=m;j<=n;j++)
        {
            pNext = pCur->next;
            pCur->next = pPre;
            pPre = pCur;
            pCur = pNext;
        }
        if(m != 1)
        {
            pPreM->next = pPre;
        }
        pM->next = pNext;
        return m==1? pPre : head;
    }

};

 3.K個一組反轉連結串列

給你一個連結串列,每 k 個節點一組進行翻轉,請你返回翻轉後的連結串列。

k 是一個正整數,它的值小於或等於連結串列的長度。

如果節點總數不是 k 的整數倍,那麼請將最後剩餘的節點保持原有順序。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* reverseKGroup(ListNode* head, int k) {
        //先反轉以head開頭的k個元素
        //將第k+1個元素作為head遞迴呼叫reverseKGroup函式
        //將上述兩個過程的結果連線起來
        //base case 如果最後的元素不足k個,就保持不變
        if(head == nullptr)
            return nullptr;
        ListNode* a = head;
        ListNode* b = head;
        for(int i=0;i<k;i++)
        {
            if(b == nullptr)
                return head;
            b = b->next;
        }
        ListNode* newHead = reverse(a,b);
        a->next = reverseKGroup(b,k);
        return newHead;
    }
    ListNode* reverse(ListNode* a, ListNode* b)
    {
        ListNode* pCur = a;
        ListNode* pPre = nullptr;
        ListNode* pNext = nullptr;
        while(pCur != b)
        {
            pNext = pCur->next;
            pCur->next = pPre;
            pPre = pCur;
            pCur = pNext;
        }
        return pPre;

    }
};

&n