「这是我参与2022首次更文挑战的第3天,活动详情查看:2022首次更文挑战」。
每日刷题第25天 2021.1.20
回文链表
- leetcode原题链接:leetcode-cn.com/problems/pa…
- 难度:简单
- 方法:双指针、栈
易错点(笔记📒)
链表
- 空链表
- 链表中只有一个元素
- 链表中当前节点
cur和调用某节点的next时,一定要判断当前节点是否为空
回文串
a b a、a(不要遗漏情况)a b b a
题目
- 给你一个单链表的头节点
head,请你判断该链表是否为回文链表。如果是,返回true;否则,返回false。
示例
- 示例1
输入: head = [1,2,2,1]
输出: true
- 示例2
输入: head = [1,2]
输出: false
提示
- 链表中节点数目在范围
[1, 105]内 0 <= Node.val <= 9进阶: 你能否用O(n)时间复杂度和O(1)空间复杂度解决此题?
解法
分析思路
- 回文串有两种情况符合:
- 奇数
[1,2,1] 或 [1] - 偶数
[1,2,2,1]注意⚠️:不要忘记奇数情况
- 奇数
整体的解题思路
奇数举例:[1,2,1]
- 用快慢指针找到链表的中点,将链表分为两部分
[1]和[2,1] - 前半部分存入栈
stack中,后半部分开头由slow指针指向(小细节:栈中只需要存储当前节点的val值即可)。因此此时的stack = [1], slow = [2,1] - 因为链表长度是奇数,需要将
slow指针指向下一个节点,slow = [1](长度为奇数时,中间的节点可以和自身形成回文) - 此时比较
stack = [1] 和 slow = [1]的val是否完全相同即可。 - 补充:链表长度为
1,即:[5],这种情况可以提前进行判断,直接返回true
偶数举例:[1,2,2,1]
- 用快慢指针找到链表的中点,将链表分为两部分
[1,2]和[2,1] - 前半部分存入栈
stack中,后半部分开头由slow指针指向(小细节:栈中只需要存储当前节点的val值即可)。因此此时的stack = [1,2], slow = [2,1] - 因为链表长度是偶数,故直接比较
stack = [1,2] 和 slow = [2,1]的val是否完全相同即可。
代码展示
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode} head
* @return {boolean}
*/
var isPalindrome = function(head) {
// 快慢指针 + 栈
if (head.next == null) return true;
let fast = head;
let slow = head;
// 开一个栈
let stack = [];
// 获取链表的长度
let len = 0;
while (fast) {
len++;
fast = fast.next;
}
fast = head;
while (fast && fast.next) {
// 找到尾部,跳出循环
stack.push(slow.val);
fast = fast.next.next;
slow = slow.next;
}
// 分偶数和奇数的情况
// 1.奇数情况下,后半段会多一个数字
let flag = false;
while (stack && slow) {
// 链表长度为奇数 且 第一次进入
if (len % 2 == 1 && !flag){
slow = slow.next;
flag = true;
}
if (stack.pop() != slow.val) {
// 不相等
return false;
}
slow = slow.next;
}
return true;
};