最長(zhǎng)連續(xù)回文串Swift實(shí)現(xiàn)

題目:Longest Palindromic Substring

Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000.

Example:

Input: "babad"

Output: "bab"

Note: "aba" is also a valid answer.

Example:

Input: "cbbd"

Output: "bb"

算法分析

解法一:

暴力解法轻专,時(shí)間復(fù)雜度:O(n^n)。

遍歷每一個(gè)字符攻臀,然后左右依次向兩邊比較是否相等幔嫂,繼而判斷是否滿足回文串的條件,找出最長(zhǎng)即可瘪撇。注意需要判斷回文長(zhǎng)度為奇获茬,偶長(zhǎng)度的情況。

解法二:

  • 動(dòng)態(tài)規(guī)劃倔既,時(shí)間復(fù)雜度:O(n^2)恕曲。
    dp[i][j] 表示從i~j的子串是否是回文串。

動(dòng)態(tài)轉(zhuǎn)移方程:

dp[i][j] = {
    dp[i-1][j + 1] : s[i] == s[j],
    false          : s[i] != s[j]
}

Swift實(shí)現(xiàn)

class Solution {
    func longestPalindrome(_ s: String) -> String {
        var dp:[[Bool]] = [];
        if s.count <= 1{
            return s;
        }
        
        var longest:Int = 1;
        var left:Int = 0;
        var right:Int = 0;
        
        for var i in 0...s.count - 1{
            var eachRow:[Bool] = [];
            for var j in 0...s.count - 1{
                if i == j{
                    eachRow.append(true);
                }else{
                    eachRow.append(false);
                }
            }
            dp.append(eachRow);
        }
        
        var i:Int = 0;
        var j:Int = 0;
        for var character_j in s {
            if j == 0 {
                j += 1;
                continue;
            }
            i = 0;
            for var character_i in s {
                if character_i == character_j {
                    dp[i][j] = dp[i + 1][j - 1] || j - i <= 1;
                    if dp[i][j] && j - i + 1 > longest{
                        longest = j - i + 1;
                        left = i;
                        right = j;
                    }
                }else{
                    dp[i][j] = false;
                }
                i += 1;
                if i >= j{
                    break;
                }
            }
            j += 1;
        }
        let leftIndex = s.index(s.startIndex, offsetBy: left);
        let rightIndex = s.index(s.startIndex, offsetBy: right);
        return String(s[leftIndex...rightIndex]);
    }
}

AC結(jié)果:可能是swift處理字符串的效率問(wèn)題會(huì)超時(shí)渤涌。

Time Limit Exceeded

第三種解法

  • Manacher算法,時(shí)間復(fù)雜度:O(n)佩谣。

Manacher's ALGORITHM: O(n)時(shí)間求字符串的最長(zhǎng)回文子串思路分析這里介紹的很清晰,
此處只是簡(jiǎn)單介紹與Swift實(shí)現(xiàn)实蓬。

首先解決回文長(zhǎng)度為奇偶的問(wèn)題

  • 插樁處理茸俭,整個(gè)字符串的前后間隔處插入'#'字符,最終得到的字符串就一定是奇數(shù)長(zhǎng)度安皱,回文的長(zhǎng)度也一定是奇數(shù)長(zhǎng)度调鬓。

我們來(lái)舉一個(gè)例子:"cbbd"。先進(jìn)行插樁處理 -> "#c#b#b#d#"酌伊。我們定義一個(gè)數(shù)組P[i]用來(lái)記錄以i處的字符作為軸心的最大的回文半徑腾窝。我們自己計(jì)算得到如下的對(duì)應(yīng)關(guān)系:

# c # b # b # d #
1 2 1 2 3 2 1 2 1

解決計(jì)算P[i]問(wèn)題

我們?cè)黾觾蓚€(gè)輔助量id,max分別代表當(dāng)前計(jì)算的到最右邊回文覆蓋的軸心與最右下標(biāo)。借用Manacher's ALGORITHM: O(n)時(shí)間求字符串的最長(zhǎng)回文子串中的兩張圖解:

當(dāng) mx - i > P[j] 的時(shí)候,以S[j]為中心的回文子串包含在以S[id]為中心的回文子串中虹脯,由于 i 和 j 對(duì)稱驴娃,以S[i]為中心的回文子串必然包含在以S[id]為中心的回文子串中,所以必有 P[i] = P[j]循集,見(jiàn)下圖唇敞。

Longest Palindromic Substring_1.png

當(dāng) P[j] >= mx - i 的時(shí)候,以S[j]為中心的回文子串不一定完全包含于以S[id]為中心的回文子串中咒彤,但是基于對(duì)稱性可知厚棵,下圖中兩個(gè)綠框所包圍的部分是相同的,也就是說(shuō)以S[i]為中心的回文子串蔼紧,其向右至少會(huì)擴(kuò)張到mx的位置婆硬,也就是說(shuō) P[i] >= mx - i。至于mx之后的部分是否對(duì)稱奸例,就只能老老實(shí)實(shí)去匹配了彬犯。


Longest Palindromic Substring_2.png

得到的計(jì)算的方程式:

//記j = 2 * id - i,也就是說(shuō) j 是 i 關(guān)于 id 的對(duì)稱點(diǎn)(j = id - (i - id))
P[i] = {
    P[j] ,mx - i > P[j]
    mx - i, mx - i <= P[j]
}

Swift 實(shí)現(xiàn)

class Solution {
    func longestPalindrome(_ s: String) -> String {
        if s.count <= 1 {
            return s;
        }
    
        // 1.間隔之間先插入#
        var newString:String = "#";
        for var character in s {
            newString.append(character);
            newString = newString + "#";
        }
        let characters = Array(newString);
        
        // 2.遍歷找出以每個(gè)節(jié)點(diǎn)作為軸最長(zhǎng)半徑
        var maxId:Int = 0;
        var max:Int = 0;
        var ids:[Int] = [];
        ids.append(1);
        var maxLength:Int = 1;
        var maxLengthIndex = 0;
        
        for var i in 1...characters.count - 1 {
            var j:Int = maxId - (i - maxId);
            if max > i && j >= 0 {
                ids.append(min(ids[j], max - i));
            }else{
                ids.append(1);
            }
            while i + ids[i] <= characters.count - 1 && i - ids[i] >= 0 && characters[i + ids[i]] == characters[i - ids[i]]{
                ids[i] += 1;
            }
            
            if i + ids[i] - 1 > max {
                maxId = i;
                max = i + ids[i] - 1;
            }
            
            if ids[i] > maxLength{
                maxLength = ids[i];
                maxLengthIndex = i;
            }
        }
        let leftIndex = s.index(s.startIndex, offsetBy: (maxLengthIndex - (maxLength - 1))/2);
        let rightIndex = s.index(leftIndex, offsetBy:maxLength - 1 - 1);
        return String(s[leftIndex...rightIndex]);
    }
}

AC結(jié)果:

Accepted

參考

https://www.felix021.com/blog/read.php?2040

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末查吊,一起剝皮案震驚了整個(gè)濱河市谐区,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌逻卖,老刑警劉巖宋列,帶你破解...
    沈念sama閱讀 210,978評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異评也,居然都是意外死亡炼杖,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門(mén)盗迟,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)坤邪,“玉大人,你說(shuō)我怎么就攤上這事罚缕⊥Х模” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,623評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵邮弹,是天一觀的道長(zhǎng)黔衡。 經(jīng)常有香客問(wèn)我,道長(zhǎng)腌乡,這世上最難降的妖魔是什么盟劫? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,324評(píng)論 1 282
  • 正文 為了忘掉前任,我火速辦了婚禮导饲,結(jié)果婚禮上捞高,老公的妹妹穿的比我還像新娘。我一直安慰自己渣锦,他們只是感情好硝岗,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,390評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著袋毙,像睡著了一般型檀。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上听盖,一...
    開(kāi)封第一講書(shū)人閱讀 49,741評(píng)論 1 289
  • 那天胀溺,我揣著相機(jī)與錄音,去河邊找鬼皆看。 笑死仓坞,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的腰吟。 我是一名探鬼主播无埃,決...
    沈念sama閱讀 38,892評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼毛雇!你這毒婦竟也來(lái)了嫉称?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,655評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤灵疮,失蹤者是張志新(化名)和其女友劉穎织阅,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體震捣,經(jīng)...
    沈念sama閱讀 44,104評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡荔棉,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了蒿赢。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片江耀。...
    茶點(diǎn)故事閱讀 38,569評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖诉植,靈堂內(nèi)的尸體忽然破棺而出祥国,到底是詐尸還是另有隱情,我是刑警寧澤晾腔,帶...
    沈念sama閱讀 34,254評(píng)論 4 328
  • 正文 年R本政府宣布舌稀,位于F島的核電站,受9級(jí)特大地震影響灼擂,放射性物質(zhì)發(fā)生泄漏壁查。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,834評(píng)論 3 312
  • 文/蒙蒙 一剔应、第九天 我趴在偏房一處隱蔽的房頂上張望睡腿。 院中可真熱鬧语御,春花似錦、人聲如沸席怪。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,725評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)挂捻。三九已至碉纺,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間刻撒,已是汗流浹背骨田。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,950評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留声怔,地道東北人态贤。 一個(gè)月前我還...
    沈念sama閱讀 46,260評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像醋火,于是被迫代替她去往敵國(guó)和親抵卫。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,446評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容

  • “你身體還好嗎胎撇?昨天夢(mèng)見(jiàn)你回來(lái)了介粘。”剛睡醒晚树,媽媽打來(lái)電話姻采。 其實(shí),距離離開(kāi)家爵憎,還不到一周慨亲。 突然感覺(jué)很感傷,明白自...
    木蕭鳴閱讀 246評(píng)論 1 1
  • “主人,五一到了你準(zhǔn)備去哪玩坝拚 蛉签?”電話那頭傳來(lái)包奕凡的聲音×ち龋“睡覺(jué)啊碍舍,這幾天累死了∫匮牛”“那可不行片橡,我好不容易才...
    LT_Tamia_92e5閱讀 462評(píng)論 0 0
  • 1、依據(jù)官方文檔進(jìn)行如下配置: 2淮野、在build的時(shí)候可能會(huì)報(bào)依賴包沖突異常捧书,在build.gradle中添加如下...
    紫苓閱讀 762評(píng)論 0 1
  • 一個(gè)人對(duì)你好不好经瓷, 取決于你在他心里重不重要爆哑。 看重你,給你的都是踏實(shí)依靠了嚎; 看輕你,給你的都是虛無(wú)縹緲廊营。 一顆心...
    漂浮的流云閱讀 344評(píng)論 2 3