一、题目描述
给你一个单链表的头节点 head
,请你判断该链表是否为回文链表。如果是,返回 true
;否则,返回 false
。
示例 1:
输入:head = [1,2,2,1] 输出:true
示例 2:
输入:head = [1,2] 输出:false
提示:
- 链表中节点数目在范围
[1, 105]
内 0 <= Node.val <= 9
二、思路
判断回文链表,通俗的讲就是判断链表的前后半部分是否对应相等,我们可以将链表分成两部分,再将后半部分链表反转,分成两个链表,然后逐一对应检验同位的节点值是否相等即可
三、实现步骤
(1)找到链表的中间节点。这里我们运用到快慢指针的思想,当快节点(一次走两步及以上)走到尾部时,慢节点指向中间部分,返回中间节点
ListNode* s=head,*f=head;
ListNode* pre=head;//定义一个pre指针,后面用来分隔链表
while(f&&f->next){
pre=s;
f=f->next->next;
s=s->next;
}
pre->next=nullptr;
分割链表
(2)反转后半部分链表,封装一个反转链表的函数
ListNode* reversalList(ListNode* head){
ListNode* cur=head;
ListNode* pre=nullptr;
while(cur){
ListNode* temp=cur->next;
cur->next=pre;
pre=cur;
cur=temp;
}
return pre;
}
(3)最后创建两个指针分别指向两个链表的头节点,便于遍历链表,然后我们逐一进行检验,检查节点值是否对应相等,是返回true,不是则返回false
ListNode* left=head;
ListNode* right=reversalList(s);
while(left){
if(left->val!=right->val){
return false;
}else{
right=right->next;
left=left->next;
}
}
return true;
}
四、具体算法代码
class Solution {
public:
bool isPalindrome(ListNode* head) {
if(head==nullptr||head->next==nullptr){
return true;
}
ListNode* s=head,*f=head;
ListNode* pre=head;
while(f&&f->next){
pre=s;
f=f->next->next;
s=s->next;
}
pre->next=nullptr;//分割链表
ListNode* left=head;
ListNode* right=reversalList(s);//反转后半部分链表,并创建right指针指向头节点
//逐一检验值
while(left){
if(left->val!=right->val){
return false;
}else{
right=right->next;
left=left->next;
}
}
return true;
}
//封装反转链表函数
ListNode* reversalList(ListNode* head){
ListNode* cur=head;
ListNode* pre=nullptr;
while(cur){
ListNode* temp=cur->next;
cur->next=pre;
pre=cur;
cur=temp;
}
return pre;
}
};
五、总结
链表题的思路很多都有相似的地方,这里建议大家多运用封装函数的思想,熟悉运用一些操作,例如反转链表、查找中间节点等,一定要多画图理解过程。