LeetCode - 234. 回文链表

发布于:2025-09-03 ⋅ 阅读:(21) ⋅ 点赞:(0)

问题

234. 回文链表 - 力扣(LeetCode)

思路

首先,我需要找到链表的中点,这里使用快慢指针技巧 - slow指针每次走一步,fast指针每次走两步。当fast到达链表尾部时,slow就正好在中间位置。

然后关键的一步是处理链表长度的奇偶性:

  • 如果fast不为空,说明链表长度是奇数,这时中间节点不应该参与比较,所以我从slow的下一个节点开始反转
  • 如果fast为空,说明链表长度是偶数,直接从slow开始反转后半部分

接着我用递归方式反转后半部分链表 - 递归到链表末尾,然后在回溯过程中重新连接指针,把方向反过来。

最后,比较原链表前半部分与反转后的后半部分,如果它们对应位置的值都相同,那么这就是一个回文链表。

这个算法的时间复杂度是O(n),我们只需要遍历链表常数次。空间复杂度主要来自递归调用栈,是O(n/2),也就是O(n)

读者可能出现的错误写法

class Solution {
public:
    bool isPalindrome(ListNode* head) 
    {
        ListNode* slow = head;
        ListNode* fast = head;
        while(fast && fast->next)
        {
            slow = slow->next;
            fast = fast->next->next;
        }
        ListNode newlist = reserve(slow->next);
        bool result = compare(head,newlist);
        return result;
    }
    ListNode* reserve(ListNode* head)
    {
        if(!head || !head->next)
        {
            return head;
        }

        ListNode* newHead = reserve(head->next);
        head->next->next = head;
        head->next = nullptr;

        return newHead;
    }

    bool compare(ListNode* head1,ListNode* head2)
    {
        while(head1&&head2)
        {
            if(head1->val == head2->val)
            {
                head1 = head1->next;
                head2 = head2->next;
            }
            else
            {
                return false;
            }
        }
        return true;
    }
}; 

这个方法有一个问题,对于奇数长度的链表会出错。

问题在于:当链表长度为奇数时,中间节点不应该参与比较。但你的代码中,直接反转了从中点开始的所有节点,导致前半部分比后半部分多出节点。也就是说,当快慢指针走完之后,需要进行判断是否是奇数,如果是奇数就直接跳过slow->next,如果不是奇数就使用slow

正确写法

class Solution {
public:
    bool isPalindrome(ListNode* head) 
    {
        ListNode* slow = head;
        ListNode* fast = head;
        ListNode* newlist = nullptr;
        while(fast && fast->next)
        {
            slow = slow->next;
            fast = fast->next->next;
        }
        if(fast)
        {
            newlist = reserve(slow->next);
        }
        else
        {
            newlist = reserve(slow);
        }
        bool result = compare(head,newlist);
        return result;
    }
    ListNode* reserve(ListNode* head)
    {
        if(!head || !head->next)
        {
            return head;
        }

        ListNode* newHead = reserve(head->next);
        head->next->next = head;
        head->next = nullptr;

        return newHead;
    }

    bool compare(ListNode* head1,ListNode* head2)
    {
        while(head1 && head2)
        {
            if(head1->val == head2->val)
            {
                head1 = head1->next;
                head2 = head2->next;
            }
            else
            {
                return false;
            }
        }
        return true;
    }
};

网站公告

今日签到

点亮在社区的每一天
去签到