题目:
请判断一个链表是否为回文链表。
示例:
输入: 1->2 输出: false
输入: 1->2->2->1 输出: true
解题思路:
如果是数组求回文就很简单。我们可以使用双指针法来比较两端的元素,并向中间移动。一个指针从起点向中间移动,另一个指针从终点向中间移动。
然而这里是在链表中,因为不论是正向访问还是反向访问都不是 O(1)。而将链表的值复制到数组列表中是 O(n),因此最简单的方法就是将链表的值复制到数组列表中,再使用双指针法判断。
时间和空间复杂度都是O(n)
题目问能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题?
这里主要介绍比较经典的双指针法,时间复杂度为O(n),空间复杂度为O(1)
思路:
a. 定义快慢双指针
b. 关键点:找出mid,快指针前进2步,慢指针前进1步,最后循环结束慢指针为中间值
c. 以mid为head进行后半段的反转
d. 前半段与后半段的Val值依次比较,只要有对不上的立刻返回
实现:
//go func isPalindrome(head *ListNode) bool { if head == nil { return true } firstHalfEnd := endOfFirstHalf(head) secondHalfStart := reverseList(firstHalfEnd.Next) p1, p2 := head, secondHalfStart var res = true for res && p2 != nil { if p1.Val != p2.Val { return false } p1 = p1.Next p2 = p2.Next } // 反转恢复链表,写不写都可 // firstHalfEnd.Next = reverseList(secondHalfStart) return res } // 找出中间节点 func endOfFirstHalf(head *ListNode) *ListNode { slow, first := head, head for first.Next != nil && first.Next.Next != nil { slow = slow.Next first = first.Next.Next } return slow } // 反转链表 func reverseList(head *ListNode) *ListNode { var pre, cur *ListNode = nil, head for cur != nil { tmpNext := cur.Next cur.Next = pre pre = cur cur = tmpNext } return pre }
地址:https://mp.weixin.qq.com/s/AnpDP3mkfFMabU2mMiNg_g