cpp
复制代码
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};*/
#include <cstddef>
// 反转链表函数:将链表反转并返回新的头节点
struct ListNode* reverseList(struct ListNode* head){
struct ListNode *newhead = NULL; // 新链表的头节点(初始为空)
struct ListNode *cur = head; // 当前处理的节点
// 遍历原链表,逐个节点反转
while(cur) {
struct ListNode *next = cur->next; // 保存下一个节点的指针
// 将当前节点连接到新链表的头部
cur->next = newhead;
newhead = cur; // 更新新链表的头节点为当前节点
cur = next; // 处理下一个节点
}
return newhead; // 返回后的链表头节点
}
class PalindromeList {
public:
bool chkPalindrome(ListNode* A) {
// 思路:通过快慢指针针找到链表中点,反转后半部分,再与前半部分比较
// 特殊情况处理:空链表或单节点链表都是回文
if(A == NULL || A->next == NULL) return true;
ListNode *fast = A; // 快指针(一次走两步)
ListNode *slow = A; // 慢指针(一次走一步)
ListNode *prev = NULL; // 用于记录慢指针的前一个节点
// 1. 找到链表的中点
// 当快指针到达尾部时,慢指针刚好在中点位置
while(fast && fast->next) {
prev = slow; // 保存慢指针当前位置
slow = slow->next; // 慢指针前进一步
fast = fast->next->next; // 快指针前进两步
}
// 2. 将前半部分链表的尾部断开(与后半部分分离)
prev->next = NULL;
// 3. 反转后半部分链表
slow = reverseList(slow);
// 4. 比较前半部分和反转后的后半部分
while(A) { // 前半部分遍历完即结束
// 若对应节点值不相等,则不是回文
if(A->val != slow->val)
return false;
else {
A = A->next; // 前半部分后移
slow = slow->next; // 后半部分后移
}
}
// 所有对应节点值都相等,是回文
return true;
}
};
/* 样例讲解:
假设链表为:1 -> 2 -> 3 -> 2 -> 1(是回文)
步骤1:找中点
- 初始:fast=1, slow=1, prev=NULL
- 第一次循环:prev=1, slow=2, fast=3
- 第二次循环:prev=2, slow=3, fast=1(fast->next为NULL,退出循环)
此时slow指向中点3,prev指向2
步骤2:断开前半部分
prev->next=NULL → 前半部分变为:1->2
步骤3:反转后半部分
原后半部分:3->2->1 → 反转后:1->2->3
步骤4:比较两部分
- A=1, slow=1 → 相等
- A=2, slow=2 → 相等
- A=NULL(前半部分结束)→ 循环退出
返回true,判断为回文
另一个样例:1->2->3->4(不是回文)
步骤1:找中点后,前半部分1->2,后半部分3->4
步骤2:反转后半部分为4->3
步骤3:比较1 vs 4 → 不相等,返回false
*/