LeetCode 234——回文鏈表
阿新 • • 發佈:2018-10-14
val www fast struct 精彩 反轉鏈表 每一個 復雜度 lis
1. 題目
請判斷一個鏈表是否為回文鏈表。
示例 1:
輸入: 1->2
輸出: false
示例 2:
輸入: 1->2->2->1
輸出: true
進階:
你能否用 O(n) 時間復雜度和 O(1) 空間復雜度解決此題?
2. 思路
- 此題可以看做是反轉鏈表 和 鏈表中間結點 的結合。
定義快慢兩個指針,尋找中間結點,同時在慢指針移動的過程中反轉前半部分子鏈表。當找到中間結點時,再分別向前向後比較前後兩個子鏈表的每一個結點值是否相同。
- 偶數結點情況如下
此時,我們分別得到了以 slow 為頭指針的前半部分子鏈表和以 p2 為頭指針的後半部分子鏈表。由於中間結點偏向後邊,所以我們需要先比較最中間的兩個結點(此處為 2 和 3 結點)
再來看奇數結點的情況
- 奇數個結點時,我們依然可以分別得到以 slow 為頭指針的前半部分子鏈表和以 p2 為頭指針的後半部分子鏈表。此時,由於 slow 指向的中間結點無須比較,我們只需從 slow 後面第一個結點和 p2 指向的結點開始循環向兩邊比較即可(此處為 2 和 4 結點)。
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: bool isPalindrome(ListNode* head) { if (head == NULL || head->next == NULL) // 空鏈或只有一個結點,返回 true { return true; } else { /* 此為反轉鏈表的三個指針,slow 即代表 p1 */ ListNode* slow = head; // 慢指針指向第一個結點 ListNode * p2 = slow->next; // 第二個結點 ListNode * p3 = p2->next; // 第三個結點 ListNode* fast = head; // 快指針指向頭結點 // 奇數結點快指針指向最後一個結點結束 // 偶數結點快指針指向 NULL 結束 while(fast && fast->next) { p3 = p2->next; fast = fast->next->next; // 快指針前進兩步 p2->next = slow; // 反轉鏈表 slow = p2; // 慢指針前進一步 p2 = p3; } head->next = NULL; // 處理前半部分子鏈的尾節點 // 偶數結點 if(!fast) { // 先比較 slow 後的兩個結點是否相同 if (slow->val == slow->next->val) { // 以 slow 後的第三個結點和 p2 指向的結點開始循環向兩邊比較 slow = slow->next->next; while(slow) { if (slow->val != p2->val) { return false; } else { slow = slow->next; p2 = p2->next; } } return true; } else { return false; } } // 奇數結點 else { // 以 slow 後的第一個結點和 p2 指向的結點開始循環向兩邊比較 slow = slow->next; while(slow) { if (slow->val != p2->val) { return false; } else { slow = slow->next; p2 = p2->next; } } return true; } } } };
獲取更多精彩,請關註「seniusen」!
LeetCode 234——回文鏈表