该题目的要求是判断一个单链表是否是回文链表,题目的难度在于O(n)时间和O(1)空间的限制。
由于单链表不能反向访问,所以不能直接通过原来的链表来判断,解题的思路是首先对原来的链表的前半部分进行判断,然后进行判断(如链表为“12344321” 反转之后为“43214321”)。想到这一点之后的实现就非常简单了,完整的代码如下所示:
class Solution {
public:
ListNode* reverseHalf(ListNode* root){
ListNode *fast = root, *slow = root;
//slow 指向要反转的部分的后一个节点
while(fast != nullptr && fast -> next != nullptr){
fast = fast -> next -> next;
slow = slow -> next;
}
ListNode *h = new ListNode(0);
h -> next = root;
//执行反转
ListNode *sec = root, *fir = root -> next;
while(fir != slow){
sec -> next = fir -> next;
fir -> next = h -> next;
h -> next = fir;
fir = sec -> next;
}
return h -> next;
}
bool isPalindrome(ListNode* head) {
int len = 0;
ListNode* p = head;
ListNode *fast, *slow;
//计算单链表的长度
while(p != NULL){
len++;
p = p -> next;
}
if(len < 2)
return true;
//反转单链表的前半部分
ListNode* reversedList = reverseHalf(head);
//slow 指向单链表的中间位置
fast = slow = reversedList;
while(fast != nullptr && fast -> next != nullptr){
fast = fast -> next -> next;
slow = slow -> next;
}
//fast 指向单链表的头部
fast = reversedList;
if(len % 2 != 0)
slow = slow -> next;
//判断是否为回文子串
while(slow != nullptr){
if(fast -> val != slow -> val)
return false;
fast = fast -> next;
slow = slow -> next;
}
return true;
}
};