【题目描述】
给你一个单链表的头节点 head ,请你判断该链表是否为回文链表。如果是,返回 true ;否则,返回 false 。
示例1:
输入:head = [1,2,2,1]
输出:true
示例2:
输入:head = [1,2]
输出:false
注:链表中节点数目在范围[1, 10^5] 内
题目来源(力扣):回文链表
【基本思路】
先找到中间节点,借此将链表拆分为两部分,并对后半部分进行反转。
再同时遍历前半和后半部分的链表,判断相对应的两个节点的值是否相等。如果存在不相等,则该单链表一定不是回文链表。
【代码实现】
typedef struct ListNode ListNode;
//反转链表函数
ListNode* reverseList(ListNode* head){
ListNode* cur = head;
ListNode* newhead = NULL;
while (cur)
{
ListNode* next = cur->next;
cur->next = newhead;
newhead = cur;
cur = next;
}
return newhead;
}
bool isPalindrome(struct ListNode* head){
//用快慢指针法寻找中间节点
ListNode* slow = head;
ListNode* fast = head;
ListNode* prev = head; // prev是定位链表中间节点的前一个节点
while (fast && fast->next)
{
prev = slow;
slow = slow->next;
fast = fast->next->next;
}
prev->next = NULL; // 一定要对前半部分链表的末尾置空
slow = reverseList(slow); // 反转后半部分的链表
//同时遍历前半和后半部分的链表
while (head)
{
//判断相对应的两个节点的值是否相等
if (head->val != slow->val) // 如果存在不相等,则该单链表一定不是回文链表
{
return false;
}
head = head->next;
slow = slow->next;
}
//能走到这里,说明该单链表必是回文链表
return true;
}
因为此解法需拆分原链表,故最后需将链表复原为原来的样子(再加上部分代码即可)。
想详细了解上面的两个子步骤的,请点击下面两个博客链接:
链表的中间结点
反转链表
本专栏
有关链表的题目
其它专栏
有关数组的题目