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?
给定一个单链表,判断它的元素是否是回文。要求在O(n)的时间复杂度和O(1)的空间复杂度内求解。如果没有时间复杂度的限制,可以直接将链表反转再比较就可以了。但是这样时间复杂度和空间复杂度都是O(n)。
想了很久都没想明白,虽然这是道easy的题目,看了Discuss发现这道题结合了查找单链表的中间元素和反转链表这两个要求才能在O(n)的时间和O(1)的空间内求解。
基本的思想如下:
- 使用两个指针slow和fast,slow每次移动一步,fast移动两步,找到链表的中间节点;
- 将slow后面的链表进行反转;
- 将反转后的链表添加到slow后面;
- slow指针后移一位到新添加的链表首端;
- 比较head和slow的值,同时将两者不断后移
图示如下:
runtime:24ms
/**
* 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)
return true;
ListNode * slow=head;
ListNode * fast=head;
while(fast->next&&fast->next->next)
{
slow=slow->next;
fast=fast->next->next;
}
slow->next=reverseList(slow->next);
slow=slow->next;
while(slow)
{
if(slow->val!=head->val)
return false;
slow=slow->next;
head=head->next;
}
return true;
}
ListNode * reverseList(ListNode * head)
{
ListNode * pre=NULL;
ListNode * next=head;
while(head)
{
next=head->next;
head->next=pre;
pre=head;
head=next;
}
return pre;
}
};