Hot100-Day34-T234回文链表

12 阅读1分钟

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;
    }
};