题目
给你一个单链表的头节点 head
,请你判断该链表是否为回文链表。如果是,返回 true
;否则,返回 false
。
示例
输入:head = [1,2,2,1] 输出:true
方法1——将链表转换为数组
解题思路
想到我们在做数组的题目的时候也遇到过判断字符串回文的题目,使用双指针,i指向字符串第一个字符,j指向字符串最后一个字符,然后比较两个字符是否相等,不相等就返回false,相等就继续比较i++和j--指向的字符,遍历完则返回true。
现在题目意思相同,只是要判断的是链表,所以我们想到可以吧链表转换为数组,然后判断就可以啦!
代码
class Solution {
public:
bool isPalindrome(ListNode* head) {
vector<int> vec;
ListNode *p=new ListNode();
p=head;
while(p){//将链表转化为数组
vec.push_back(p->val);
p=p->next;
}
int i=0;
int j=vec.size()-1;
while(i<=j){
if(vec[i]!=vec[j]){
return false;
}
i++;
j--;
}
return true;
}
};
时间复杂度:O(n),n是链表的长度,第一次遍历将n个链表元素放入数组,时间复杂度O(n),第二次双指针遍历,时间复杂度O(n/2)
空间复杂度:O(n),n是链表元素个数,用一个数组来存放链表元素
方法2——反转后半部分链表然后比较
解题思路:
找到链表中间节点,然后反转后半部分链表,然后比较前半部分和后半部分,关于链表反转和找中间节点的思路在本链表专栏也有的哦!
/**
* 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) {
ListNode *p=head;//p指向原链表头节点
ListNode *fast=head;//快慢指针用来找中间节点
ListNode *slow=head;
while(fast&&fast->next){//slow指向中间节点(偶数各节点时指向中间后一个节点)
fast=fast->next->next;
slow=slow->next;
}
ListNode *pre=nullptr;//用于和中间节点slow一起来反转链表后半部分
while(slow){
ListNode *next=slow->next;//用来记录slow的后一个节点,不然改变slow->next后就会找不到p后面的节点
slow->next=pre;//改变链表方向
pre=slow;
slow=next;
}
//pre为后半部分链表反转后的链表
while(pre){//比较链表前半部分和反转后的后半部分
if(pre->val!=p->val){
return false;
}
pre=pre->next;
p=p->next;
}
return true;
}
};