Swift - LeetCode - 回文鏈表

題目

給你一個(gè)單鏈表的頭節(jié)點(diǎn) head,請(qǐng)你判斷該鏈表是否為回文鏈表。如果是,返回 true;否則,返回 false。

示例 1:

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

示例 2:

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

方法一:將值復(fù)制到數(shù)組中并判斷數(shù)組中元素個(gè)數(shù)

思路

如果你還不太熟悉鏈表,下面有關(guān)于列表的概要講述。

有兩種常用的列表實(shí)現(xiàn),分別為數(shù)組列表和鏈表。如果我們想在列表中存儲(chǔ)值,它們是如何實(shí)現(xiàn)的呢?

  • 數(shù)組列表底層是使用數(shù)組存儲(chǔ)值,我們可以通過(guò)索引在 O(1) 的時(shí)間訪問(wèn)列表任何位置的值,這是由基于內(nèi)存尋址的方式。
  • 鏈表存儲(chǔ)的是稱為節(jié)點(diǎn)的對(duì)象,每個(gè)節(jié)點(diǎn)保存一個(gè)值和指向下一個(gè)節(jié)點(diǎn)的指針。訪問(wèn)某個(gè)特定索引的節(jié)點(diǎn)需要 O(n) 的時(shí)間,因?yàn)橐ㄟ^(guò)指針獲取到下一個(gè)位置的節(jié)點(diǎn)。

確定數(shù)組列表是否回文很簡(jiǎn)單,我們可以使用雙指針?lè)▉?lái)比較兩端的元素,并向中間移動(dòng)。一個(gè)指針從起點(diǎn)向中間移動(dòng),另一個(gè)指針從終點(diǎn)向中間移動(dòng)。這需要 O(n) 的時(shí)間,因?yàn)樵L問(wèn)每個(gè)元素的時(shí)間是 O(1),而有 n 個(gè)元素要訪問(wèn)。

然而同樣的方法在鏈表上操作并不簡(jiǎn)單,因?yàn)椴徽撌钦蛟L問(wèn)還是反向訪問(wèn)都不是 O(1)。而將鏈表的值復(fù)制到數(shù)組列表中是 O(n),因此最簡(jiǎn)單的方法就是將鏈表的值復(fù)制到數(shù)組列表中,再使用雙指針?lè)ㄅ袛唷?/p>

算法

一共為兩個(gè)步驟:

  1. 復(fù)制鏈表值到數(shù)組列表中。
  2. 使用雙指針?lè)ㄅ袛嗍欠駷榛匚摹?/li>

第一步,我們需要遍歷鏈表將值復(fù)制到數(shù)組列表中。我們用 currentNode 指向當(dāng)前節(jié)點(diǎn)。每次迭代向數(shù)組添加 currentNode.val,并更新 currentNode = currentNode.next,當(dāng) currentNode = null 時(shí)停止循環(huán)。

第二步,我們?cè)谄瘘c(diǎn)放置一個(gè)指針,在結(jié)尾放置一個(gè)指針,每一次迭代判斷兩個(gè)指針指向的元素是否相同,若不同,返回 false;相同則將兩個(gè)指針向內(nèi)移動(dòng),并繼續(xù)判斷,直到兩個(gè)指針相遇。

代碼

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
    }
}

復(fù)雜度分析

  • 時(shí)間復(fù)雜度:O(n),其中 n 指的是鏈表的元素個(gè)數(shù)。

    • 第一步: 遍歷鏈表并將值復(fù)制到數(shù)組中,O(n)。
    • 第二步:雙指針判斷是否為回文,執(zhí)行了O(n/2) 次的判斷,即 O(n)。
    • 總的時(shí)間復(fù)雜度:O(2n) = O(n)
  • 空間復(fù)雜度:O(n),其中 n 指的是鏈表的元素個(gè)數(shù),我們使用了一個(gè)數(shù)組列表存放鏈表的元素值。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 題目 回文鏈表 問(wèn)題: 請(qǐng)判斷一個(gè)鏈表是否為回文鏈表。 進(jìn)階: 你能否用 O(n) 時(shí)間復(fù)雜度和 O(1) 空間復(fù)...
    依賴糊涂閱讀 279評(píng)論 0 1
  • 目錄 1 左神部分集錦 2 Leetcode前150題 3 ??途W(wǎng)劍指offer 4 JavaG 5 題目中的...
    小小千千閱讀 1,355評(píng)論 0 0
  • LeetCode-鏈表 鏈表(Linked List)是一種常見(jiàn)的基礎(chǔ)數(shù)據(jù)結(jié)構(gòu),是一種線性表,但是并不會(huì)按線性的順...
    raincoffee閱讀 1,323評(píng)論 0 6
  • 前言 為了養(yǎng)成創(chuàng)作習(xí)慣,從今天起開(kāi)始刷力扣了,只刷簡(jiǎn)單和中等難度的題,分類(lèi)刷,這個(gè)月就先刷鏈表題,從簡(jiǎn)單的開(kāi)始按著...
    Java技術(shù)人閱讀 128評(píng)論 0 1
  • 為了測(cè)試我們寫(xiě)的代碼是否正確,我們需要自己寫(xiě)兩個(gè)個(gè)方法,這兩個(gè)方法對(duì)于調(diào)試代碼來(lái)說(shuō)是十分有幫助的。 編寫(xiě)輔助函數(shù):...
    李威威閱讀 1,702評(píng)論 0 2

友情鏈接更多精彩內(nèi)容