LeetCode偶尔一题 —— 234. 回文链表
原文地址:https://juejin.im/post/6887059077025939469
原题地址:https://leetcode-cn.com/problems/palindrome-linked-list/
题目描述
请判断一个链表是否为回文链表。
示例 1:
输入: 1->2
输出: false
示例 2:
输入: 1->2->2->1
输出: true
进阶:
你能否用 \(O(n)\) 时间复杂度和 \(O(1)\) 空间复杂度解决此题?
解题思路
思考一个点,如果要用 \(O(1)\) 时间复杂度来解决的话,说明要利用链表本身来解决这个问题。想通这点,下面的思路就能顺其自然的想出来了👇
- 将一条链表切分成两条对称的链表
- 获取链表的中间节点以及它的节点数量
- 如果节点数量是奇数,那么可以舍去中间节点并借此分割链表,否则将中间节点分配给左侧的链表
- 反转其中一条链表
- 对比两条链表的值
代码
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head
* @return {boolean}
*/
const isPalindrome = function(head) {
/**
* 切分链表
* @param head {ListNode}
* @return {ListNode}
*/
const splitLinkList = (head) => {
let prev = null
let low = head
let fast = low.next
let nextHead = null
let cnt = 1
while (fast && fast.next) {
prev = low
low = low.next
fast = fast.next.next
cnt++
}
cnt = cnt * 2 - (fast ? 0 : 1)
nextHead = low.next
low.next = null
if (cnt % 2 === 1) {
prev.next = null
}
return nextHead
}
/**
* 反转链表
* @param head {ListNode}
* @return {void}
*/
const reverseLinkList = (head) => {
if (!head) {
return null
}
let prev = head
let next = head.next
while (next) {
head.next = next.next
next.next = prev
prev = next
next = head.next
}
return prev
}
/**
* 检查链表是否相同
* @param head {ListNode}
* @param nextHead {ListNode}
* @return {boolean}
*/
const checkLinkList = (head, nextHead) => {
if (!head && !nextHead) {
return true
}
if (!head || !nextHead || head.val !== nextHead.val) {
return false
}
return checkLinkList(head.next, nextHead.next)
}
if (!head || !head.next) {
return true
}
const nextHead = splitList(head)
head = reverseLinkList(head)
return checkLinkList(head, nextHead)
};