234. 回文链表
给你一个单链表的头节点 head
,请你判断该链表是否为回文链表
。如果是,返回 true
;否则,返回false
。
示例 1:
输入:head = [1,2,2,1]
输出:true
示例 2:
输入:head = [1,2]
输出:false
提示:
- 链表中节点数目在范围[1, 10^5] 内
- 0 <= Node.val <= 9
进阶:你能否用 O(n)
时间复杂度和 O(1)
空间复杂度解决此题?
解题思路
Go代码
/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
func isPalindrome(head *ListNode) bool {
if head == nil || head.Next == nil {
return true
}
// 找到链表的中间节点(如果节点个数是偶数,要找中间两个元素的前一个),拆成两个链表
// 注意:链表长度为偶数时,如果用fast != nil && fast.Next != nil,则最终slow停在两个中间元素的后一个
// 如果用fast.Next != nil && fast.Next.Next != nil,则最终slow停在两个中间元素的前一个,本题我们需要这种情况
slow,fast:= head,head
for fast.Next != nil && fast.Next.Next != nil {
fast = fast.Next.Next
slow = slow.Next
}
// 切割成两个链表
secondList := slow.Next
slow.Next = nil
// 反转第二个链表
secondList = reverseList(secondList)
// 从前往后比较两个链表,看看每个值是否相等
slow,fast = head,secondList
for slow != nil && fast != nil {
if slow.Val != fast.Val {
return false
}
slow = slow.Next
fast = fast.Next
}
// 后一个链表要么和第一个链表长度一致,要么少一个元素,如果他没有走完,说明不是回文的
if fast != nil {
return false
}
return true
}
func reverseList(head *ListNode) *ListNode {
// 头插法
dummy := &ListNode{}
dummy.Next = head
tail := head
cur := head.Next
for cur != nil {
nxt := cur.Next
cur.Next = dummy.Next
dummy.Next = cur
tail.Next = nxt
cur = nxt
}
return dummy.Next
}