【题目概要】
234. Palindrome Linked List
Given a singly linked list, determine if it is a palindrome.
Example 1:
Input: 1->2
Output: false
Example 2:
Input: 1->2->2->1
Output: true
Follow up:
Could you do it in O(n) time and O(1) space?
【思路分析】
- 主要是三个函数cut、reverse和isequal,其中cut是在链表的中间将其断开,其中如果是有奇数和偶数区别,reverse是将后半部分的链表翻转,采用了头插法,最后采用equal函数判断是否相等
【代码示例】
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
void cut(struct ListNode* head,struct ListNode* cutNode);
struct ListNode* reverse(struct ListNode* head);
bool IsEqual(struct ListNode* l1,struct ListNode* l2);
bool isPalindrome(struct ListNode* head){
if(head==NULL || head->next==NULL) return true;
struct ListNode* slow=head;
struct ListNode* fast=head;
while(fast!=NULL && fast->next!=NULL)
{
fast=fast->next->next; //慢指针走一步,快指针走两步,最后把单链表分为以慢指针分成两部分
slow=slow->next;
}
cut(head,slow);
if(fast!=NULL) slow=slow->next; //如果是奇数个结点,那么cut后将slow后移一位再reverse,就将中间的结点扔掉了,但其实不这么做也是可以的,因为在IsEqual函数中while的判断条件里是&&,即使不把中间的点扔掉,它也不会加入判断,结果是一样的
return IsEqual(head,reverse(slow));
}
void cut(struct ListNode* head,struct ListNode* cutNode){ //在slow结点前砍断链表
struct ListNode* p = head;
while(p->next!=cutNode)
p=p->next;
p->next=NULL;
}
struct ListNode* reverse(struct ListNode* head) //头插法*****反转后面一部分(头插法应熟练掌握)
{
struct ListNode* newHead=NULL;
while(head!=NULL)
{
struct ListNode* nextNode=head->next;
//从头部开始插入
head->next=newHead;
newHead=head;
head=nextNode;
}
return newHead;
}
bool IsEqual(struct ListNode* l1,struct ListNode* l2){
while(l1!=NULL && l2 !=NULL)
{
if(l1->val != l2->val) return false;
l1=l1->next;
l2=l2->next;
}
return true;
}