题目描述
请判断一个链表是否为回文链表。
示例 1:
输入: 1->2
输出: false
示例 2:
输入: 1->2->2->1
输出: true
进阶:
你能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题?
思路
本题目标为找到链表中点然后将中间往后的结点倒置,再依次比较大小是否相等;
找中间结点的过程需要利用快慢两个指针,其中慢指针一次走一格,快指针一次走两格,终止时,slow 指针不是在中间结点(共有奇数个结点),就是在中间结点的前一个结点(共有偶数个结点),都是从 slow->next 开始比较大小;
反转链表这一过程利用了三个指针,分别指向第一、二、三个结点(*p,*q,*r),q->next = p 和 p = q 是关键,最后 p 指向反转后链表的头结点,返回 p 即可。
代码(参考链接:http://www.cnblogs.com/BlueskyRedsea/p/9326666.html)
/**
* 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(head == NULL || head->next == NULL)
return true;
ListNode *fast = head;
ListNode *slow = head;
//快慢两指针遍历链表
while(fast->next != NULL && fast->next->next != NULL)
{
fast = fast->next->next;
slow = slow->next;
}
//两种情况都是取slow的下一个
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;
}
//颠倒slow后的链表
ListNode* reverseList(ListNode* head) {
if(head == NULL) return head;
ListNode* p,*q,*r;
p = head;
q = p->next;
p->next = NULL;
while(q){
r = q->next;
q->next = p;
p = q;
q = r;
}
return p;
}
};