一. 迭代
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);
}
};