请判断一个链表是否为回文链表。
进阶:
你能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题?
示例 1:
输入:
1->2
输出:
false
示例 2:
输入:
1->2->2->1
输出:
true
思路: 这题要做到空间O(1),时间O(n)的话只能先将链表从中间断开,再将后半部分的链表翻转与前面一个链表作比较.
方法:找到中间节点可以用快慢指针,翻转的话用三个指针去改变指向就行.
注意:为了不改变原来链表的结构,在判断完之后要把链表还原
/*
* 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;
//定义快慢指针
ListNode* slow = head;
ListNode* fast = head;
bool res = true;
//找到中间节点
while (fast->next != NULL && fast->next->next != NULL)
{
slow = slow->next;
fast = fast->next->next;
}
//翻转后半段链表
//这是指向当前节点的下一个节点额指针
ListNode* nex = NULL;
//fast指向当前要改变指向的节点
fast = slow->next;
//slow->next是要指向的节点
slow->next = NULL;
while (fast)
{
//保存下一个节点
nex = fast->next;
//当前节点指向前一个节点
fast->next = slow->next;
//前一个节点更新为当前节点,为下一次循环准备
slow->next = fast;
//当前节点更新为下一个节点,为下一次反转准备
fast = nex;
}
//保存前半段的最后一个节点,为还原做准备
nex = slow;
//当前slow->next指向的是后半段的开头节点
//这是在翻转链表的时候形成的
slow = slow->next;
//fast指向前半段头结点
fast = head;
while (slow)
{
if (slow->val != fast->val)
{
res = false;
break;
}
slow = slow->next;
fast = fast->next;
}
//再调用反转链表的代码来还原
slow = nex;
fast = slow->next;
slow->next = NULL;
while (fast)
{
nex = fast->next;
fast->next = slow->next;
slow->next = fast;
fast = nex;
}
return res;
}
};