一、介绍
1.题目描述
题目链接:https://leetcode-cn.com/problems/palindrome-linked-list/
请判断一个链表是否为回文链表。
进阶:
你能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题
- 链表是单向的
2.测试样例
[1,2] # false
[1,2,2,1] # true
二、题解
1、暴力🟢
(1)新建数组,遍历链表并将每个节点的值存储到数组中,转换为回文数组的问题。
(2)双指针从数组头尾向中间靠拢,如果出现不一样的值,则不是回文链表
class Solution {
public:
bool isPalindrome(ListNode* head) {
// temp记录数值,num统计节点个数
vector<int> temp;
int num=0;
// 遍历到末尾后结束循环
while(head!=nullptr){
// 存储值
temp.push_back(head->val);
num++;
head=head->next;
}
// 头尾指针指向的数值不一致,不是回文
for(int i=0;i<num/2;i++){
if(temp[i]!=temp[num-i-1]) return false;
}
return true;
}
};

2、栈🟢
(1)遍历一次链表,得到链表长度 n。
(2)指针从头向后移,依次将n/2个元素推入栈
(3)此时指针在后半截起始的位置,依次弹出栈元素并和当前指向的元素值对比,不同则不是回文
class Solution {
public:
bool isPalindrome(ListNode* head) {
int n=0;
ListNode *p=head;
// 统计链表长度
while(p!=nullptr){
n++;
p=p->next;
}
if(n==1) return true;
stack<int> stk;
p=head;
int k=(n+1)/2; // 一半的位置
// 向栈中推入前半截元素,结束后指针在后半截起始处
for(int i=0;i<k;i++){
stk.push(p->val);
p=p->next;
}
// 弹出栈元素,和后半截依次对比
// 如果链表长度为奇数,要弹出居中的数再开始比较
if(n%2!=0) stk.pop();
while(p!=nullptr){
if(stk.top()!=p->val) return false;
stk.pop();
p=p->next;
}
return true;
}
};

3、快慢指针🟡
思路:设置快慢指针,快指针 q 一次移动2格,慢指针 p 1格,慢指针移动的同时对链表反转。当快指针到头,慢指针在中间位置。此时从中间和开头分别遍历,比较数值是否相同
- 如果链表长度为奇数,居中的数反转后在开头,但不参与比较,从开头的下一个节点开始比较
- 利用flag标志长度奇偶。快指针在第一次移动发现已经是末尾,说明是偶数。在第二次移动发现是末尾,说明是奇数
class Solution {
public:
bool isPalindrome(ListNode* head) {
if(head->next==nullptr) return true;
ListNode *p=head,*q=head,*pre=nullptr;
int flag=0;
while(q->next!=nullptr){
q=q->next;
if(q->next!=nullptr){
// q 后移
q=q->next;
// p指向的后一个节点插入到链表开头【即对前半截反转】
pre=p->next;
p->next=p->next->next;
pre->next=head;
head=pre;
}
// 如果尾指针第二次后移发现已经到头,说明是奇数
else flag=1;
}
// 尾指针指向链表后半截起始处
q=p->next;
// 如果是奇数,从头节点下一个开始比较
p=flag==0?head->next:head;
// 不同则不是回文
while(q!=nullptr){
if(q->val!=p->val) return false;
q=q->next;
p=p->next;
}
return true;
}
};

4、 递归🔴
① pre 为头指针,head为尾指针。
② 通过递归,head不断后移,指向末尾,比较末尾与初始位的数值是否相同
- 若不同,逐层返回 false,结果为 false
- 若相同,pre后移,向上一层返回 true,比较上一层【即倒数第二个节点和整数第二个节点】值是否相同
③ 重复步骤2直至递归结束
class Solution {
ListNode *pre;
public:
bool isPalindrome(ListNode* head) {
pre=head;
return huiwen(head);
}
bool huiwen(ListNode* head){
if(head!=nullptr){
if(huiwen(head->next)==false) return false;
if(head->val!=pre->val) return false;
pre=pre->next;
}
return true;
}
};

该博客围绕LeetCode上判断链表是否为回文的题目展开。介绍了四种解法,包括暴力法将链表值存数组用双指针判断,栈法将前半元素入栈与后半对比,快慢指针法边移动边反转链表后比较,递归法通过前后指针递归比较数值。

360

被折叠的 条评论
为什么被折叠?



