给你一个单链表的头节点
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)
空间复杂度解决此题?
思路:
- 找到前半部分链表的尾节点
- 反转后半部分链表
- 判断是否回文
恢复链表并返回结果- 注意 isPalindrome() 中的判断条件:cur2 != nil; 因为后半部分链表在反转后的尾节点为空(cur2可能会遍历到空节点导致出错);且对于奇数长度的链表,前半部分长度更长(比如:5=3+2),所以只判断后半部分的cur2不为空即可~
时间复杂度:O(N)
空间复杂度:O(1)
/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
func isPalindrome(head *ListNode) bool {
if head == nil {
return true
}
firstHalfEnd := endOfFirstHalf(head)
secondHalfStart := reverseList(firstHalfEnd.Next) // 注意传入中点的Next节点
for cur1, cur2 := head, secondHalfStart; cur2 != nil; { // 因为后半部分反转后的尾节点为空(cur2可能会遍历到空节点导致出错),且对于奇数长度的链表,前半部分长度更长(比如:5=3+2)
if cur1.Val != cur2.Val {
return false
}
cur1 = cur1.Next
cur2 = cur2.Next
}
return true
}
// 通过快慢指针寻找链表中点,此时slow指向链表的中点
func endOfFirstHalf(head *ListNode) *ListNode {
var fast, slow *ListNode = head, head
for fast.Next != nil && fast.Next.Next != nil { // 注意判断条件
fast = fast.Next.Next
slow = slow.Next
}
return slow
}
// 反转后半部分链表
func reverseList(head *ListNode) *ListNode {
var pre, mid, end *ListNode = nil, head, nil
for mid != nil {
end = mid.Next
mid.Next = pre
pre = mid
mid = end
}
return pre
}