Swift - LeetCode - 回文链表

题目

给你一个单链表的头节点 head,请你判断该链表是否为回文链表。如果是,返回 true;否则,返回 false

示例 1:

  • 输入:head = [1,2,2,1]
  • 输出:true

示例 2:

  • 输入:head = [1,2]
  • 输出:false

方法一:将值复制到数组中并判断数组中元素个数

思路

如果你还不太熟悉链表,下面有关于列表的概要讲述。

有两种常用的列表实现,分别为数组列表和链表。如果我们想在列表中存储值,它们是如何实现的呢?

  • 数组列表底层是使用数组存储值,我们可以通过索引在 O(1) 的时间访问列表任何位置的值,这是由基于内存寻址的方式。
  • 链表存储的是称为节点的对象,每个节点保存一个值和指向下一个节点的指针。访问某个特定索引的节点需要 O(n) 的时间,因为要通过指针获取到下一个位置的节点。

确定数组列表是否回文很简单,我们可以使用双指针法来比较两端的元素,并向中间移动。一个指针从起点向中间移动,另一个指针从终点向中间移动。这需要 O(n) 的时间,因为访问每个元素的时间是 O(1),而有 n 个元素要访问。

然而同样的方法在链表上操作并不简单,因为不论是正向访问还是反向访问都不是 O(1)。而将链表的值复制到数组列表中是 O(n),因此最简单的方法就是将链表的值复制到数组列表中,再使用双指针法判断。

算法

一共为两个步骤:

  1. 复制链表值到数组列表中。
  2. 使用双指针法判断是否为回文。

第一步,我们需要遍历链表将值复制到数组列表中。我们用 currentNode 指向当前节点。每次迭代向数组添加 currentNode.val,并更新 currentNode = currentNode.next,当 currentNode = null 时停止循环。

第二步,我们在起点放置一个指针,在结尾放置一个指针,每一次迭代判断两个指针指向的元素是否相同,若不同,返回 false;相同则将两个指针向内移动,并继续判断,直到两个指针相遇。

代码

class Solution {
    func isPalindrome(_ head: ListNode?) -> Bool {
        if nil == head {
            return false
        }
        var vals: [Int] = []
        var currentNode: ListNode? = head
        while nil != currentNode {
            vals.append(currentNode!.val)
            currentNode = currentNode!.next
        }
        
        var i = 0
        while i < (vals.count / 2) {
            if vals[i] != vals[vals.count - 1 - i] {
                return false
            }
            i += 1
        }
        return true
    }
}

复杂度分析

  • 时间复杂度:O(n),其中 n 指的是链表的元素个数。

    • 第一步: 遍历链表并将值复制到数组中,O(n)
    • 第二步:双指针判断是否为回文,执行了O(n/2) 次的判断,即 O(n)
    • 总的时间复杂度:O(2n) = O(n)
  • 空间复杂度:O(n),其中 n 指的是链表的元素个数,我们使用了一个数组列表存放链表的元素值。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 题目 回文链表 问题: 请判断一个链表是否为回文链表。 进阶: 你能否用 O(n) 时间复杂度和 O(1) 空间复...
    依赖糊涂阅读 262评论 0 1
  • 目录 1 左神部分集锦 2 Leetcode前150题 3 牛客网剑指offer 4 JavaG 5 题目中的...
    小小千千阅读 1,121评论 0 0
  • LeetCode-链表 链表(Linked List)是一种常见的基础数据结构,是一种线性表,但是并不会按线性的顺...
    raincoffee阅读 1,282评论 0 6
  • 前言 为了养成创作习惯,从今天起开始刷力扣了,只刷简单和中等难度的题,分类刷,这个月就先刷链表题,从简单的开始按着...
    Java技术人阅读 105评论 0 1
  • 为了测试我们写的代码是否正确,我们需要自己写两个个方法,这两个方法对于调试代码来说是十分有帮助的。 编写辅助函数:...
    李威威阅读 1,676评论 0 2