请判断一个链表是否为回文链表。
示例 1:
输入: 1->2
输出: false
示例 2:
输入: 1->2->2->1
输出: true
进阶:
你能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题?
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* reverseList(struct ListNode *head);
bool isPalindrome(struct ListNode* head) {
//找到单链表的中间结点。
//链表长度为奇数(2n+1)时索引为n。
//如1->2->3->2->1, 则中间结点为3.
//链表长度为偶数2n时为n-1。
//如1->2->3->3->2->1, 则中间结点为第一个3.
//链表中间结点的确定可以采取快慢指针的方法,快指针每次循环前进两步,慢指针每次循环前进一步,当快指针到达链表的结尾时,慢指针指向的结点恰好是链表的中间结点。
//将中间结点之后的一半链表进行反转。
//反转之后只需要进行一次扫描就可以得出结论。
if(head == NULL || head->next == NULL)
return true;
struct ListNode *fast = head;
struct ListNode *slow = head;
while(fast->next != NULL && fast->next->next != NULL)
{
fast = fast->next->next;
slow = slow->next;
}
slow->next = reverseList(slow->next);
slow = slow->next;
while(slow != NULL)
{
if(head->val != slow->val)
return false;
head = head->next;
slow = slow->next;
}
return true;
}
struct ListNode* reverseList(struct ListNode *head)
{
struct ListNode *pre = NULL;
struct ListNode *next = NULL;
while(head != NULL)
{
next = head->next;
head->next = pre;
pre = head;
head = next;
}
return pre;
}