回文链表
题目:
请判断一个链表是否为回文链表。
示例:
输入: 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
    small_lei_it  技术无止境,追求更高。
 
                    
                     
                    
                 
                    
                
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号