解决思路
举例来说,假设此时链表结构为1-> 2 -> 3 -> 4 -> 5 -> 6
。
我们可以将其拆分为两个链表1-> 2 -> 3
和4 -> 5 -> 6
。然后我们反转第二个链表为6 -> 5 -> 4
。
之后对两个链表进行比较,其时间复杂度O(n)
,空间复杂度O(1)
。
代码
class Solution {
public:
bool isPalindrome(ListNode* head) {
ListNode *mid = nullptr, *tail = nullptr, *p = head;
int size = listSize(head);
bool isPalind;
if(size == 1 || size == 0)
return true;
for(int i = 0; i < size / 2; i++){
mid = p;
p = p->next;
}
tail = mid->next;
mid->next = nullptr;
tail = reverseList(tail);
isPalind = isSame(head, tail);
// restore list
tail = reverseList(tail);
mid->next = tail;
return isPalind;
}
/* get list size */
int listSize(ListNode* head){
int size = 0;
for(; head != nullptr; head = head->next)
size++;
return size;
}
ListNode * reverseList(ListNode *head){
ListNode *pre = nullptr;
while(head){
ListNode *next = head->next;
head->next = pre;
pre = head;
head = next;
}
return pre;
}
/* head's len <= tail's len */
bool isSame(ListNode *head, ListNode *tail){
while(head){
if(head->val != tail->val)
return false;
head = head->next;
tail = tail->next;
}
return true;
}
};
进一步优化
为获取链表的中间节点,我们采取的方式是先获取链表的大小,再查找中间位置。其实可以通过差速查找的方式进行。
我们可以定义两个指针pslow
和pfast
。
其中pslow
的步进方式为pslow = pslow->next
。
其中pfast
的步进方式为pfast = pfast->next->next
。
那么当pfast == nullptr
时,pslow
应为中间节点。
此代码为直接摘录他人代码
class Solution {
public:
bool isPalindrome(ListNode* head) {
ListNode *pfast = head, *pr, *pl, *pt;
if (!pfast || !(pfast->next)) {
return true;
}
pl = head;
pr = head->next;
pfast = pfast->next;
head->next = NULL;
while (pfast->next && pfast->next->next) {
pfast = pfast->next->next;
pt = pr->next;
pr->next = pl;
pl = pr;
pr = pt;
}
pr = pfast->next ? pr->next : pr;
while (pr) {
if (pl->val != pr->val) {
return false;
} else {
pl = pl->next;
pr = pr->next;
}
}
return true;
}
};