本文主要是介绍【leetcode100-024】【链表/快慢指针】回文链表,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
【题干】
给你一个单链表的头节点 head
,请你判断该链表是否为回文链表。如果是,返回 true
;否则,返回 false
。
进阶:你能否用 O(n)
时间复杂度和 O(1)
空间复杂度解决此题?
【思路】
- 判回文,一般就两种思路,两头向中间判断直到相遇,或者从对称轴向两边判断直到边界。
- 拿到链表的话,一时间看起来两种方式都不适配,因为不管哪一种都需要两个相反的枚举方向,而链表是单向枚举的结构。到这步想必也能意识到了,这题应该是要逆置半条链来做的。
- 总结一下就是
- 找链表中点,常规操作快慢指针;
- 逆置后半段,按进阶要求那就原地逆置;
- 逐节点比对两段链表,直到后半段结束,可以排除奇数情况下正中间节点对判断的影响。
- 虽然本题不需要,但可以习惯好一点,把逆置的后半段再转回来~
补充一个递归方式逆向输出单链表的方法,虽然本题用不上。
function print_values_in_reverse(ListNode head)if head is NOT nullprint_values_in_reverse(head.next)print head.val
【题解】
class Solution {
public:bool isPalindrome(ListNode* head) {if (head == nullptr) {return true;}// 找到前半部分链表的尾节点并反转后半部分链表ListNode* firstHalfEnd = endOfFirstHalf(head);ListNode* secondHalfStart = reverseList(firstHalfEnd->next);// 判断是否回文ListNode* p1 = head;ListNode* p2 = secondHalfStart;bool result = true;while (result && p2 != nullptr) {if (p1->val != p2->val) {result = false;}p1 = p1->next;p2 = p2->next;} // 还原链表并返回结果firstHalfEnd->next = reverseList(secondHalfStart);return result;}ListNode* reverseList(ListNode* head) {ListNode* prev = nullptr;ListNode* curr = head;while (curr != nullptr) {ListNode* nextTemp = curr->next;curr->next = prev;prev = curr;curr = nextTemp;}return prev;}ListNode* endOfFirstHalf(ListNode* head) {ListNode* fast = head;ListNode* slow = head;while (fast->next != nullptr && fast->next->next != nullptr) {fast = fast->next->next;slow = slow->next;}return slow;}
};
这篇关于【leetcode100-024】【链表/快慢指针】回文链表的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!