回文链表

题目:

请判断一个链表是否为回文链表。

示例:

输入: 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

 

 

posted @ 2020-09-28 10:01  small_lei_it  阅读(102)  评论(0编辑  收藏  举报