首先想到的是遍历一次,知道链表长度,然后第二次遍历将前半部分入栈与后面的比较。
func isPalindrome(head *ListNode) bool {
count := 0
tmp := head
for tmp != nil {
count++
tmp = tmp.Next
}
if count==1{
return true
}
hou_index := (count+1)/2
qian_index := count/2-1
// 用于单数或者双数个数链表
arr := make([]int, qian_index+1)
tmp = head
for i:=0; i<=qian_index; i++ {
arr[i] = tmp.Val
tmp = tmp.Next
}
for i:=qian_index+1; i<hou_index; i++ {
tmp = tmp.Next
}
index := qian_index
for tmp != nil {
if tmp.Val != arr[index] {
return false
}
index -= 1
tmp = tmp.Next
}
return true
}
这个思路依赖回文链表对称的特点,看了一下相关标签有双指针的解法。
慢指针每次走1步,快指针每次走2步。快指针到末尾时,慢指针在中点(奇数为正中,偶数为前半部分末尾)。但是顺序比较是不行的,可以将后半部分链表翻转,然后再比较。
func isPalindrome(head *ListNode) bool {
fast := head
slow := head
for fast != nil && fast.Next != nil {
slow = slow.Next
fast = fast.Next.Next
}
// 从当前slow所在位置开始翻转
curr := slow
//pre := nil (use of untyped nil in assignment)
var pre *ListNode
for curr != nil {
tmp := curr.Next
curr.Next = pre
pre = curr
curr = tmp
}
// 比较
other_half_list := pre
for other_half_list != nil {
if other_half_list.Val != head.Val {
return false
}
other_half_list = other_half_list.Next
head = head.Next
}
return true
}