题目:
Given a singly linked list, determine if it is a palindrome.
Follow up:
Could you do it in O(n) time and O(1) space?
/**
* 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 (NULL == head || NULL == head->next) return true;
//快慢指针找到中点 O(n) O(1)
ListNode *slow = head, *fast = head->next;
bool res = true;
while (fast != NULL && fast->next != NULL){
slow = slow->next;
fast = fast->next->next;
}
ListNode *headSecond = slow->next;
ListNode *tailFirst = slow;
slow->next = NULL;
//翻转后半部分 O(n) O(1)
headSecond = reverseList(headSecond);
//从头逐个比较每个节点 O(n) O(1)
ListNode *p1 = head, *p2 = headSecond;
while (p2 != NULL){
if (p1->val != p2->val) {
res = false;
break;
}
p1 = p1->next;
p2 = p2->next;
}
/*恢复链表结构*/
//翻转后半部分组成的链表
headSecond = reverseList(headSecond);
//将它连入前半部分链表的最后一个节点
tailFirst->next = headSecond;
return res;
}
private:
ListNode *reverseList(ListNode *head){
if (NULL == head || NULL == head->next) return head;
ListNode *p = head->next, *headNew = head;
head->next = NULL;
while (p != NULL){
ListNode *pNext = p->next;
p->next = headNew;
headNew = p;
p = pNext;
}
return headNew;
}
};
注:链表的长度可能是奇数页可能是偶数,如果是奇数,最中间的一个节点是前半部分链表的最后一个节点,即前半部分链表比后半部分链表多一个节点;如果是偶数,两部分链表长度相同。