思路
- 快慢指针,快指针遍历到链表末尾附近时,慢指针到达链表中间位置附近,以此找到中间位置
- 慢指针遍历的同时对链表进行反转
- 从中间位置分别向两头遍历,同时进行比较
注意,笔者之所以使用附近两字描述,是因为要根据链表节点的数量(奇、偶)分情况讨论
func isPalindrome(head *ListNode) bool {
if head == nil || head.Next == nil {
return true
}
slowPtr, fastPtr := head, head
pre := (*ListNode)(nil)
for fastPtr != nil && fastPtr.Next != nil {
fastPtr = fastPtr.Next.Next
// 慢指针遍历过程中同时反转链表
next := slowPtr.Next
slowPtr.Next = pre
pre = slowPtr
slowPtr = next
}
var toLeft, toRight *ListNode
//单链表有 偶数 个节点
if fastPtr == nil {
toLeft = pre
toRight = slowPtr
}else if fastPtr.Next == nil{
//单链表有 奇数 个节点
toLeft = pre
toRight = slowPtr.Next
}
for toLeft != nil && toRight != nil {
if toLeft.Val != toRight.Val {
return false
}
toLeft = toLeft.Next
toRight = toRight.Next
}
return true
}