该题思路上最容易想到的还是我们将这些结点的值全部填到一个数组或者一个string里面去,之后按照之前所学的判断是否是回文串的方法来做即可
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {//转string
public:
bool isPalindrome(ListNode* head) {
bool sign=true;
string str="";
for(ListNode *p=head;p;p=p->next)
{
str+=p->val;//填入string
}
for(int i=0,j=str.length()-1;i<j;i++,j--)//双指针判断是否是回文串
{
if(str[i]!=str[j])
{
sign=false;
break;
}
}
return sign;
}
};
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {//转数组
public:
bool isPalindrome(ListNode* head) {
vector<int> num;
ListNode *p=head;
int sign=true;
while(p!=nullptr)
{
num.push_back(p->val);//一个一个存入数组
p=p->next;
}
for(int i=0,j=num.size()-1;i<j;i++,j--)//双指针判断是否是回文串
{
if(num[i]!=num[j])
{
sign=false;
break;
}
}
return sign;
}
};
不过这里着重来讲的还是我们的快慢指针(快慢指针的效率相比上面两种方法更高一些)
我发现快慢指针(双指针)在链表里面还是蛮常用的
整个算法分为以下五步
- 找到前半部分链表的尾节点(即中间结点)。点击查看如何查找链表的中间结点
- 反转后半部分链表。点击查看如何实现反转链表(迭代/双指针)
- 判断是否回文。
- 恢复链表。
- 返回结果。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* find_firsthalfend(ListNode* head)//寻找中间结点
{
ListNode *fast=head;//快慢指针
ListNode *slow=head;
while(fast!=nullptr&&fast->next!=nullptr)
{
fast=fast->next->next;//当快指针到达终点的时候,慢指针即到达中点
slow=slow->next;
}
return slow;//返回中间结点
}
ListNode* reverselist(ListNode *firsthalfend)
{
ListNode* slow=nullptr;
ListNode* fast=firsthalfend;//快慢指针
while(fast!=nullptr)
{
ListNode* temp=fast->next;//保存下一个结点
fast->next=slow;每次都让快指针指向慢指针(即实现部分反转)
slow=fast;//二者都向前走一步
fast=temp;
}
return slow;//返回反转后的头结点
}
bool isPalindrome(ListNode* head) {
if(head==nullptr)//排除链表为空
{
return false;
}
ListNode *firsthalfend=find_firsthalfend(head);//找到中间结点
ListNode *last=reverselist(firsthalfend);//反转后半段链表
ListNode *pbegin=head;//复制头结点
bool sign=true;
while(sign&&last!=nullptr)//判断是否为回文串(有点像双指针)
{
if(last->val!=pbegin->val)
{
sign=0;
break;
}
pbegin=pbegin->next;
last=last->next;
}
firsthalfend=reverselist(firsthalfend);//将反转的链表转回来(毕竟使用这个函数的人不会希望自己的链表被改变)
return sign;
}
};