Description:
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?
判断一个链表是否是回文链表
注意条件......
算法思考:
1.先用一个数组存储正向的链表的每一个结点的值,再使用单链表的就地逆置 ,用另一个数组存储逆向链表每一个结点的值,最后做比较
此做法空间复杂度超出 为O(n)
2.遍历整个链表,将链表每个结点的值存入数组,再判断数组是否是一个回文数组,空间复杂度 O(n) ,时间复杂度O(n)
3.使用快慢指针找链表中点法,找到链表的中点,然后将后半链表就地逆置,再分别一一判断是否相等,该办法时间复杂度O(n),空间复杂度O(1)
选用后半逆转:
bool isPalindrome(struct ListNode* head) {
struct ListNode *fast,*slow;
if(head==NULL)
return NULL;
if(head->next==NULL)
return true;
fast=slow=head;
//快慢指针找链表中点
while(fast&&fast->next) //条件一个都不能少,因为链表节点个数可能为为奇数或偶数
{
slow=slow->next;
fast=fast->next->next;
}
if(fast) //结点数为奇数
{
slow->next=reverse(slow->next);
slow=slow->next;
}
else
slow=reverse(slow);
while(slow)
{
if(slow->val!=head->val)
return false;
slow=slow->next;
slow=slow->next;
}
return true;
}
就地逆置函数:
struct ListNode* reverse(struct ListNode* head) //注意head不是头结点,是第一个结点
{
struct ListNode *phead,*p1,*p2;
phead=(struct ListNode*)malloc(sizeof(struct ListNode));
phead->next=p1=head;
phead->next=NULL;
while(p1)
{
p2=p1;
p1=p1->next;
p2->next=phead->next;
phead->next=p2;
}
}