Loading

[LeetCode] 234. Palindrome Linked List(回文单链表)

Description

Given a singly linked list, determine if it is a palindrome.

给定一个单链表,判断其是否为回文结构。

Examples

Example 1

Input: 1->2
Output: false

Example 2

Input: 1->2->2->1
Output: true

Follow up

Could you do it in O(n) time and O(1) space?

你能用 O(N) 时间复杂度和 O(1) 空间复杂度解决吗?

Solution

普通的解法比较简单:两次遍历,第一次遍历时将链表所有值压入栈内;第二次遍历时,从栈内依次弹出元素值与之进行比较。由于栈先进后出的特性,这时弹出元素的顺序恰好与输入顺序相反,如果链表是回文结构,这两个序列应该是相同的,代码如下:

/**
 * Example:
 * var li = ListNode(5)
 * var v = li.`val`
 * Definition for singly-linked list.
 * class ListNode(var `val`: Int) {
 *     var next: ListNode? = null
 * }
 */
class Solution {
    fun isPalindrome(head: ListNode?): Boolean {
        if (head == null) {
            return true
        }

        val stack = ArrayDeque<Int>()
        var p = head
        while (p != null) {
            stack.push(p.`val`)
            p = p.next
        }

        p = head
        while (p != null) {
            if (p.`val` != stack.pop()) {
                return false
            }
            p = p.next
        }

        return true
    }
}

当然,上述方法中,不需要将链表的所有元素入栈,只需把链表的前半段元素入栈即可进行判断。进阶解法(要求 O(1) 空间复杂度)也不是很难,大致分为以下几个步骤:

  1. 找到链表的中点(双指针法)

  2. 反转链表的后半段

  3. 进行比较

  4. (可选)如果题目要求不能改变链表结构,那么记得程序结束前把链表还原

代码如下:

/**
 * Example:
 * var li = ListNode(5)
 * var v = li.`val`
 * Definition for singly-linked list.
 * class ListNode(var `val`: Int) {
 *     var next: ListNode? = null
 * }
 */
class Solution {
    fun isPalindrome(head: ListNode?): Boolean {
        if (head?.next == null) {
            return true
        }

        val mid = midNode(head)
        val head2 = reverse(mid)

        var p = head
        var q = head2
        while (p != null && q != null) {
            if (p.`val` != q.`val`) {
                return false
            }
            p = p.next
            q = q.next
        }

        return true
    }

    private fun midNode(head: ListNode?): ListNode? {
        if (head == null) {
            return head
        }
        var slow = head
        var fast = head

        while (slow != null && fast != null) {
            slow = slow.next
            fast = fast.next?.next
        }

        return slow
    }

    private fun reverse(head: ListNode?): ListNode? {
        var pre: ListNode? = null
        var mHead = head

        while (mHead != null) {
            val next = mHead.next
            mHead.next = pre
            pre = mHead
            mHead = next
        }

        return pre
    }
}
posted @ 2020-10-21 09:30  Zhongju.copy()  阅读(58)  评论(0编辑  收藏  举报