问题描述
给你一个单链表的头节点 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)
空间复杂度解决此题?
解法一:查找中间节点 + 翻转链表
我们可以将链表的后半部分反转(修改链表结构),然后将前半部分和后半部分进行比较。比较完成后我们应该将链表恢复原样。虽然不需要恢复也能通过测试用例,但是使用该函数的人通常不希望链表结构被更改。
该方法虽然可以将空间复杂度降到 O(1)
,但是在并发环境下,该方法也有缺点。在并发环境下,函数运行时需要锁定其他线程或进程对链表的访问,因为在函数执行过程中链表会被修改。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
|
/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
func isPalindrome(head *ListNode) bool {
// 处理空链表情况
if head == nil {
return true
}
midNode := middleNode(head)
// 开始时如果不处理 head == nil 的情况,访问 midNode.Next 会导致程序 panic,因为 midNode 此时为 nil
b := reverseList(midNode.Next)
midNode.Next = nil
a := head
copyB := b
res := true
for a != nil && b != nil {
if a.Val != b.Val {
res = false
break
}
a = a.Next
b = b.Next
}
// 开始还原
midNode.Next = reverseList(copyB)
// 验证是否还原
for head != nil {
fmt.Printf("%d ", head.Val)
head = head.Next
}
return res
}
func middleNode(head *ListNode) *ListNode {
if head == nil {
return nil
}
slow, fast := head, head
for fast.Next != nil && fast.Next.Next != nil {
slow = slow.Next
fast = fast.Next.Next
}
return slow
}
func reverseList(head *ListNode) *ListNode {
var prev *ListNode
for head != nil {
next := head.Next
head.Next = prev
prev = head
head = next
}
return prev
}
|
解法二:递归
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
func isPalindrome(head *ListNode) bool {
frontNode := head
var check func(head *ListNode) bool
// check(node) 检查以 node 为头节点的链表是否是回文链表
check = func(head *ListNode) bool {
if head == nil {
return true
}
if !check(head.Next) {
return false
}
if head.Val != frontNode.Val {
return false
}
frontNode = frontNode.Next
return true
}
return check(head)
}
|