Day34[26/4/3]T234回文链表
给你一个单链表的头节点 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) 空间复杂度解决此题?
解题思路
先用快慢指针找中点(每轮快指针走两步,慢指针走一步,然后快指针到终点,慢指针到中点);
再对后半部分反转(用三指针反转是最优的);
最后从头到中间,从尾到中间,双指针判断回文。
Code
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)
{
// 1. 先快慢指针找中点
ListNode *pfast = head;
ListNode *pslow = head;
while (pfast->next != nullptr && pfast->next->next != nullptr)
{
pfast = pfast->next->next;
pslow = pslow->next;
}
// 2. 再对后半部分反转
ListNode *pprev = nullptr; // 前一个
ListNode *pcurr = pslow->next; // 当前
ListNode *pnext = nullptr;
pslow->next = nullptr; // 断开,前半部分独立
while (pcurr != nullptr)
{
pnext = pcurr->next; // 先存下一个
pcurr->next = pprev; // 反转
pprev = pcurr; // prev前移
pcurr = pnext; // curr前移
}
ListNode *ptail = pprev;
// 3. 判断回文
while (ptail != nullptr)
{
if (head->val != ptail->val)
{
return false;
}
head = head->next;
ptail = ptail->next;
}
return true;
}
};