给你一个单链表的头节点 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) 空间复杂度解决此题?
解答一
将链表中节点保存到一个Map中,key 为节点的次序,value 为节点。对比 Map 中第 n 个节点与第 total - n -1 个节点的值是否相等。
ts
/**
* Definition for singly-linked list.
* class ListNode {
* val: number
* next: ListNode | null
* constructor(val?: number, next?: ListNode | null) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
* }
*/
function isPalindrome(head: ListNode | null): boolean {
if (!head) return false
const nodeMap = new Map<number,ListNode>()
let count = 0
while(head) {
nodeMap.set(count,head)
head = head.next
count++
}
const total = count
count = 0
const middle = Math.floor(total/2)
while(count < middle) {
if (nodeMap.get(count).val !== nodeMap.get(total-count-1).val) {
return false
}
count++
}
return true
};
**
**
时间复杂度O(n + n/2),空间复杂度O(n)
解答二
- 定义两个指针,fast 和 low,fast 的移动速度是 low 的两倍,当fast移动到链表末尾时,low就移动到了链表中间
- 反转 low 到链表末尾这部分节点
- 将 fast 重置到链表头,同步移动fast和low,比较他们指向的节点值是否相等,不相同则不是回文链表
ts
/**
* Definition for singly-linked list.
* class ListNode {
* val: number
* next: ListNode | null
* constructor(val?: number, next?: ListNode | null) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
* }
*/
function isPalindrome(head: ListNode | null): boolean {
if (!head) return false
let fast = head
let low = head
while(fast && fast.next) {
fast = fast.next.next
low = low.next
}
// 如果 fast 不为 null,则说明传入的链表节点数为奇数
if (fast) {
low = low.next
}
low = reserve(low)
fast = head
while(low) {
if (fast.val !== low.val) {
return false
}
low = low.next
fast = fast.next
}
return true
};
function reserve(head: ListNode):ListNode {
let prev = null
let current = null
while(head) {
prev = current
current = head
head = head.next
current.next = prev
}
return current
}
时间复杂度O(n),空间复杂度O(1)