一. 迭代
1. 邊移動快慢指針邊反轉鏈表的前半部分,等找到鏈表中點,再將前半部分與後半部分依次比較,判斷是否爲迴文鏈表.
//大佬的思路, 反轉後半部分.
class Solution {
public:
//題解:快慢指針法,快指針走兩步,慢指針走一步,找到鏈表的中點。然後,翻轉後半部分。最後從頭、中點開始判斷是否相同。
bool isPalindrome(ListNode* head) {
if(!head||!head->next)return true;
ListNode *fast=head,*slow=head,*pre=nullptr;
//1、找到鏈表的中點,鏈表長度奇偶不影響
while(fast&&fast->next){
slow=slow->next;
fast=fast->next->next;
}
//2、將slow之後鏈表進行斷開且反轉,最後翻轉完成之後pre指向反轉鏈表的頭節點
while(slow){
ListNode *p=slow->next;
slow->next=pre;
pre=slow;
slow=p;
}
//3、前後鏈表進行比較,注意若爲奇數鏈表,後半部分回比前部分多1一個節點,然而我們只比較相同長度的節點值,巧妙地避開這點判斷
while(head&&pre){
if(head->val!=pre->val)return false;
head=head->next;
pre=pre->next;
}
return 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==NULL || head->next==NULL) return true;
ListNode* pre = NULL;
ListNode* slow = head;
ListNode* fast = head;
while(fast!=NULL && fast->next!=NULL) {
//fast必須放在前面,因爲slow後會反轉鏈表,
//造成fast->next取不到正確的.
fast = fast->next->next;
ListNode* tmp = slow->next;
slow->next = pre;
pre = slow;
slow = tmp;
}
//畫圖可知, 當偶數時是正確的,奇數時需要slow往前next,這樣正好比較
//相同的數字.
if(fast!=NULL && fast->next==NULL) slow = slow->next;
while(slow!=NULL) {
if(slow->val!=pre->val) return false;
slow = slow->next;
pre = pre->next;
}
return true;
}
};
二. 遞歸
1. 我自己的遞歸方法,特別慢.
class Solution {
public:
ListNode* findLast(ListNode* head, int len) {
if(len==1) return head;
if(len==2) return head->next;
ListNode* last = findLast(head->next, len-2);
return last->next;
}
bool isPalindromeN(ListNode* head, int len) {
//遞歸終止.
if(len==0 || len==1) return true;
//head->next,len-2長度是否迴文.
bool flag = isPalindromeN(head->next, len-2);
//找到末尾節點,進行比較.
ListNode* last = findLast(head, len);
if(head->val==last->val) return flag;
else return false;
}
bool isPalindrome(ListNode* head) {
if(head==NULL || head->next==NULL) return true;
ListNode* cur = head;
int len = 0;
//求出鏈表長度
while(cur!=NULL) {
len++;
cur = cur->next;
}
//函數作用返回head頭結點,len長度鏈表是否迴文.
return isPalindromeN(head, len);
}
};
2. 參考官方的.
class Solution {
public:
ListNode* front = NULL;
bool isPalindromeCheck(ListNode* head) {
//遞歸終止.
if(head==NULL) return true;
//如果不滿足迴文,直接false.
if(!isPalindromeCheck(head->next)) return false;
//依次比較尾部節點和頭結點判斷是否迴文.
if(head->val!=front->val) return false;
//更新頭結點.
front = front->next;
return true;
}
bool isPalindrome(ListNode* head) {
if(head==NULL || head->next==NULL) return true;
//定義一個頭結點用於比較.
front = head;
return isPalindromeCheck(head);
}
};