LeetCode 234——迴文連結串列
阿新 • • 發佈:2018-12-15
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」!