一、問題描述
請判斷一個鏈表是否爲迴文鏈表。
示例 1:
輸入: 1->2
輸出: false
示例 2:
輸入: 1->2->2->1
輸出: true
二、解題思路
將鏈表分爲兩段,並且把後面一段進行倒置,然後再比較前後兩段是否相同即可。最簡單的方法就是先計算鏈表的長度,然後將前面一半用頭插法的辦法進行倒置,最後再比較,但是由於需要的是一半這個特殊的位置,所以我們可以考慮快慢指針,何謂快慢指針,其實就是兩個指針,一根指針一次移動一個位置,另一個指針一次移動兩個位置。快慢指針適合用於有中點相關的場景(有中點或倍數的時候可以考慮快慢指針來解決問題)
三、代碼實現
/**
* 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 || !head->next) return true;
ListNode *slow = head, *fast = head;
while (fast && fast->next) //快慢指針法,讓slow指向鏈表中部位置
{
slow = slow->next;
fast = fast->next->next;
}
//退出時,fast爲最後一個結點或者null,slow處在中間位置
//與結點數有關,左子鏈表head~slow-1, 右子鏈表爲slow~end
//右子鏈表比左子鏈表長一或者相等)
//例:0~10,slow 5, fast 10; 0~9,slow5,fast null (0表示頭結點,slow和fast的起點)
ListNode* right = reverseList(slow);//反轉右邊鏈表
ListNode* left = head;
while(left && right)//比較左右子鏈表是否相等
{
if(left->val == right->val)
{
left = left->next;
right = right->next;
}
else
return false;
}
return true;
}
private:
ListNode* reverseList(ListNode* head) {
//pre永遠指向null,相當於一個尾節點
ListNode* pre = NULL;
ListNode* cur = head;
while(cur != NULL){
//next用來保存下一個節點。因爲會把當前節點cur拿下來,賦值給pre
ListNode* next = cur->next;
cur->next = pre;
pre = cur;
cur = next;
}
return pre;
}
};