234. 回文链表

234. 回文链表

easy

给你一个单链表的头节点 head ,请你判断该链表是否为回文链表。如果是,返回 true ;否则,返回 false

image-20220808114349967

快慢指针 + 反转

利用快慢指针将链表分割成前后两部分,然后反转后半部分链表,就可以一一比较了

 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
package linked_list

func isPalindrome(head *ListNode) bool {
	if head == nil {
		return true
	}
	slow, fast := head, head
	for fast.Next != nil && fast.Next.Next != nil {
		slow = slow.Next
		fast = fast.Next.Next
	}
    // slow 即为前半部分的尾节点,如果链表为奇数,那么slow为中间节点

	startOfSecondHalf := reverseList(slow.Next) // 后半部分的头节点 顺便反转一下后半部分

	p, q := head, startOfSecondHalf
	for q != nil {
		if p.Val != q.Val {
			return false
		}
		p, q = p.Next, q.Next
	}
	return true

}

func reverseList(head *ListNode) *ListNode {
	if head == nil {
		return nil
	}
	var pre, cur *ListNode = nil, head
	for cur != nil {
		tmp := cur.Next
		cur.Next = pre
		pre, cur = cur, tmp
	}
	return pre
}

时间复杂度:O(n),其中 n 指的是链表的大小。

空间复杂度:O(1),我们只会修改原本链表中节点的指向,而在堆栈上的堆栈帧不超过 O(1)