大家好,我是小卡皮巴拉
文章目录
目录
每篇前言
博客主页:小卡皮巴拉
咱的口号:🌹小比特,大梦想🌹
作者请求:由于博主水平有限,难免会有错误和不准之处,我也非常渴望知道这些错误,恳请大佬们批评斧正。
力扣题目:回文链表
原题链接:回文链表
题目描述
给定一个链表的 头节点
head
,请判断其是否为回文链表。如果一个链表是回文,那么链表节点序列从前往后看和从后往前看是相同的。
示例 1:
输入: head = [1,2,3,3,2,1]
输出: true示例 2:
输入: head = [1,2]
输出: false
解题思路
问题理解
题目要求我们判断一个给定的链表是否为回文链表。回文链表意味着链表节点序列从前往后看和从后往前看是相同的。例如,链表
1->2->3->2->1
是回文的,而链表1->2->3->4->5
不是。算法选择
为了解决这个问题,我们可以采用以下步骤:
找到链表的中间节点:使用快慢指针法,快指针每次移动两步,慢指针每次移动一步,当快指针到达链表末尾时,慢指针正好在链表的中间。
反转链表的后半部分:从中间节点开始,反转链表的后半部分。
比较前半部分和反转后的后半部分:逐个节点比较前半部分和反转后的后半部分的节点值,如果所有节点值都相同,则链表是回文的。
具体思路
找到链表的中间节点:
使用快慢指针法,快指针
fast
每次移动两步,慢指针slow
每次移动一步。当
fast
或fast->next
为空时,slow
指向链表的中间节点。反转链表的后半部分:
从中间节点开始,使用三指针法反转链表的后半部分。
初始化三个指针
s1
(新链表的头节点,初始为NULL
),s2
(当前节点,初始为中间节点),s3
(下一个节点,初始为s2->next
)。在循环中,将
s2->next
指向s1
,然后移动指针:s1
指向s2
,s2
指向s3
,s3
指向s3->next
。当
s2
为空时,反转完成,s1
是反转后的链表头节点。比较前半部分和反转后的后半部分:
初始化两个指针
left
和right
,分别指向链表的前半部分和反转后的后半部分的头节点。在循环中,逐个比较
left
和right
节点的值,如果不相等,则返回false
。移动指针
left
和right
,直到right
为空。如果所有节点值都相等,则返回
true
。
题目要点
快慢指针法:用于找到链表的中间节点。
三指针法反转链表:用于反转链表的后半部分。
节点值比较:用于判断链表是否为回文。
完整代码(C语言)
/** * Definition for singly-linked list. * struct ListNode { * int val; * struct ListNode *next; * }; */ typedef struct ListNode ListNode; //找中间结点 ListNode* middleNode(ListNode* head) { //快慢指针找到中间结点 ListNode* slow = head; ListNode* fast = head; while(fast && fast->next) { slow = slow->next; fast = fast->next->next; } return slow; } //反转链表 ListNode* reverseList(ListNode* head) { if(head == NULL) { return head; } //三指针法反转后半段链表 ListNode* s1 = NULL,* s2 = head,*s3 = head->next; while(s2) { s2->next = s1; s1 = s2; s2 = s3; if(s3) s3 = s3->next; } return s1; } bool isPalindrome(struct ListNode* head) { //思路:1.找中间结点 2.反转以中间结点为头的后半段链表 //3.遍历比较前半段链表和后半段链表,若完全相同则回文 //找中间结点 ListNode* mid = middleNode(head); //反转以中间结点为头的后半段链表 ListNode* right = reverseList(mid); //左半段链表 ListNode* left = head; //遍历比较前半段链表和后半段链表 while(right) { if(left->val != right->val) { return false; } left = left->next; right = right->next; } return true; }
兄弟们共勉 !!!
码字不易,求个三连
抱拳了兄弟们!