链表——回文链表

给你一个单链表的头节点 head ,请你判断该链表是否为回文链表。如果是,返回 true ;否则,返回 false 。

这道题要求判断一个但来年表是否是回文链表正序和逆序完全一样),最优解法是:

快慢指针找中点+反转后半链表+前后同时遍历比较
时间复杂度** O(n),空间复杂度 O(1)**,不占用额外空间

解题思路

1.快慢指针找中点

  • 快指针走两步,慢指针走一步
  • 快指针到末尾时,慢指针正好在链表中点

2.反转后半链表

  • 从中点开始,把后半段链表反转

3.前后两段逐一比较

  • 前半段从头开始,后半段从反转后的新头开始
  • 逐个节点对比,全部相等就是回文

完整代码实现如下

#include
using namespace std;

// 链表节点定义
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) {
if (head == nullptr || head->next == nullptr) {
return true; // 空链表或单个节点一定是回文
}

// 1. 快慢指针找中点
ListNode* slow = head;
ListNode* fast = head;
while (fast != nullptr && fast->next != nullptr) {
slow = slow->next;
fast = fast->next->next;
}

// 2. 反转后半段链表
ListNode* prev = nullptr;
ListNode* cur = slow;
while (cur != nullptr) {
ListNode* temp = cur->next;
cur->next = prev;
prev = cur;
cur = temp;
} // 循环结束后 prev 是后半段反转后的头节点

// 3. 前后两段逐一比较
ListNode* left = head;
ListNode* right = prev;
while (right != nullptr) {
if (left->val != right->val) {
return false;
}
left = left->next;
right = right->next;
}

return true; // 全部匹配
}
};

// 测试代码
int main() {

// 测试回文链表 1->2->2->1
ListNode* head1 = new ListNode(1);
head1->next = new ListNode(2);
head1->next->next = new ListNode(2);
head1->next->next->next = new ListNode(1);

// 测试非回文链表 1->2
ListNode* head2 = new ListNode(1);
head2->next = new ListNode(2);

Solution sol;
cout << boolalpha;
cout << "1->2->2->1: " << sol.isPalindrome(head1) << endl; // true
cout << "1->2: " << sol.isPalindrome(head2) << endl; // false

return 0;
}

代码逐段解释

1.快慢指针找中点
ListNode* slow = head;
ListNode* fast = head;
while (fast != nullptr && fast->next != nullptr) {
slow = slow->next;
fast = fast->next->next;
}

  • 快指针一次走两步,慢指针一次走一步
  • 结束时,slow 指向链表中点(后半段起点)

2. 反转后半段链表(标准反转逻辑)
ListNode* prev = nullptr;
ListNode* cur = slow;
while (cur != nullptr) {
ListNode* temp = cur->next;
cur->next = prev;
prev = cur;
cur = temp;
}

  • 反转后,prev 变成后半段新头
  • 例如:2 -> 1 反转为 1 -> 2

3.前后两段逐一比较
ListNode* left = head;
ListNode* right = prev;
while (right != nullptr) {
if (left->val != right->val) return false;
left = left->next;
right = right->next;
}

  • 从头和从反转后的头一起走
  • 只要有一个值不相等 → 不是回文
  • 全部相等 → 是回文

四、示例运行

原链表:1 → 2 → 2 → 1
1.找到中点:slow 指向第 2 个 2
2.反转后半段:1 → 2
3.对比:
left:1 → 2
right:1 → 2
全部相等 → 返回 true

posted @ 2026-04-02 15:31  ZealousMclaren  阅读(13)  评论(0)    收藏  举报