leetcode之234回文链表Golang

这道题的限制是时间复杂度是O(n),空间复杂度是O(1),所以我们不能使用常规的方法,常规的方法就是将链表中的数据保存在数组中,然后通过数组判断是否是回文数组,这自然很简单

所以在本题,我们采用的思路就是将链表的后面半部分反转,然后再比较前面半部分和后面半部分是否相同

首先我们需要找到后面半部分,采用的方法是双指针的思路,快指针每次向后面走两步,慢指针每次向后面走一步,当快指针走到链表最后的时候,慢指针刚好走了一半,具体如下:

  • 首先如果链表是一个空链表或者链表只有一个结点,那么就直接判断这个链表就是回文链表

  • 然后将慢指针置于第一个结点,快指针置于第二个结点

    • 当链表为1 2 3 4时,当快指针指向4时候慢指针指向2

    • 当链表为1 2 3 4 5时,我们需要注意的是,因为每次快指针向后走两步,但是如果快指针走第一步的时候就到了链表末尾,那么此时快指针就走一步而慢指针不需要移动,所以此时当快指针指向5的时候,慢指针指向了2

  • 然后从慢指针的下一个结点开始反转链表

  • 此时就可以从原本的链表末尾向前遍历半个链表了,然后将第一个元素与最后一个元素比较,第二个元素与倒数第二个元素比较。。。

  • 如果中间出现了不相等的元素,那么就直接返回false,如果整个链表的元素都比较完了,那么就返回true

代码如下

func isPalindrome(head *ListNode) bool {
    // 只有一个结点或者没有结点都是回文链表
    if head == nil || head.Next == nil {
        return true
    }
    fast, slow := head.Next, head
    for fast != nil {
        if fast.Next == nil {
            break
        }
        fast = fast.Next
        if fast.Next == nil {
            break
        }
        fast = fast.Next
        slow = slow.Next
    }
    // 反转后面半部分的链表
    pre := slow.Next
    cur := pre.Next
    for cur != nil {
        cur.Next, pre, cur = pre, cur, cur.Next
    }
    reverse := pre
    for head != slow.Next {
        if head.Val == reverse.Val {
            head, reverse = head.Next, reverse.Next
        } else {
            return false
        }
    }
    return true
}

  

 

 

 

 

posted @ 2020-09-25 14:43  胖胖咩  阅读(202)  评论(0)    收藏  举报