1.题目如下:
给你一个单链表的头节点 head ,请你判断该链表是否为回文链表。如果是,返回 true ;否则,返回 false 。
示例 1:
输入:head = [1,2,2,1]
输出:true
示例 2:
输入:head = [1,2]
输出:false
提示:
链表中节点数目在范围[1, 105] 内
0 <= Node.val <= 9
进阶:你能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题?
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:
/** 思路一:用数组作为辅助空间存储节点。 空间复杂度O(n)*/
/*
bool isPalindrome(ListNode* head) {
vector<ListNode *> temp;
ListNode *s=head;
while(s!=nullptr){
temp.push_back(s);
s=s->next;
}
int i=0;
int j=temp.size()-1;
while(i<=j){
if(temp[i]->val!=temp[j]->val){
return false;
}
i++;
j--;
}
return true;
}
*/
//思路二:要节省空间,就要避免使用辅助空间,此时就要找到链表中点;寻找链表中点,用快慢指针;找到中点之后,反转后半部分的节点
//反转指针方法如下:
/*
ListNode* reverseList(ListNode* head) {
ListNode *pre=nullptr;
ListNode *curr=head;
while(curr!=nullptr){
ListNode *next=curr->next;
curr->next=pre;
pre=curr;
curr=next;
}
return pre;
}
*/
//实现:
bool isPalindrome(ListNode* head) {
if (head == nullptr) {
return true;
}
// 找到前半部分链表的尾节点并反转后半部分链表
ListNode* firstHalfEnd = endOfFirstHalf(head);
ListNode* secondHalfStart = reverseList(firstHalfEnd->next);
// 判断是否回文
ListNode* p1 = head;
ListNode* p2 = secondHalfStart;
bool result = true;
while (result && p2 != nullptr) {
if (p1->val != p2->val) {
result = false;
}
p1 = p1->next;
p2 = p2->next;
}
// 还原链表并返回结果
firstHalfEnd->next = reverseList(secondHalfStart);
return result;
}
ListNode* reverseList(ListNode* head) {
ListNode* prev = nullptr;
ListNode* curr = head;
while (curr != nullptr) {
ListNode* nextTemp = curr->next;
curr->next = prev;
prev = curr;
curr = nextTemp;
}
return prev;
}
ListNode* endOfFirstHalf(ListNode* head) {
ListNode* fast = head;
ListNode* slow = head;
while (fast->next != nullptr && fast->next->next != nullptr) {
fast = fast->next->next;
slow = slow->next;
}
return slow;
}
};