牛客:链表的回文结构详解
链表的回文结构_牛客题霸_牛客网
/*
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
*/