003-Longest Substring Without Repeating Characters

Longest Substring Without Repeating Characters

Given a string, find the length of the longest substring without repeating characters.

Examples:

Given "abcabcbb", the answer is "abc", which the length is 3.

Given "bbbbb", the answer is "b", with the length of 1.

Given "pwwkew", the answer is "wke", with the length of 3. Note that the answer must be a substring, "pwke" is a subsequence and not a substring.

Subscribe to see which companies asked this question

找出最長(zhǎng)序列的長(zhǎng)度赡译,一個(gè)可行的辦法是轉(zhuǎn)換成ascii碼,然后遍歷字符串庶香,

class Solution(object):
    def lengthOfLongestSubstring(self, s):
        """
        :type s: str
        :rtype: int
        """
        start = 0
        maxlen = 0
        hashtable = [-1 for i in range(256)]
        for i in range(len(s)):
            if hashtable[ord(s[i])] != -1:
                while start <= hashtable[ord(s[i])]:
                    hashtable[ord(s[start])] = -1
                    start += 1
            if i - start + 1 > maxlen:
                maxlen = i - start + 1
            hashtable[ord(s[i])] = i
        return maxlen

還有一個(gè)更巧妙的實(shí)現(xiàn):

class Solution(object):
    def lengthOfLongestSubstring(self, s):
        """
        :type s: str
        :rtype: int
        """
        ind = {}
        w = 0
        m = 0
        for i in range(0, len(s)):
            c = s[i]
            if i == 0:
                ind[c] = 1
                m = 1
            else:
                if c not in ind or ind[c] < w:
                    ind[c] = i+1
                    d = i+1 - w
                    m = d if d > m else m  
                else:
                    w = ind[c]
                    ind[c] = i+1            
        return m

下面的版本超級(jí)快四敞,超過(guò)了100%的提交:

class Solution(object):
    def lengthOfLongestSubstring(self, s):
        """
        :type s: str
        :rtype: int
        """
        res, f, i, m = 0, 0, -1, {}
        for v in s:
            i = i+1
            if v in m and m[v]>=f:
                if res<i-f:
                    res= i-f
                f = m[v] + 1
            m[v] = i
        if res < i+1-f:
            res=i+1-f
        return res

再來(lái)一個(gè)非常容易理解的實(shí)現(xiàn):

class Solution(object):
    def lengthOfLongestSubstring(self, s):
        """
        :type s: str
        :rtype: int
        """
        d, res, start, = {}, 0, 0
        for i, v in enumerate(s):
            if v in d:
                # update the res
                res = max(res, i-start)
                # here should be careful, like "abba"
                start = max(start, d[v]+1)
            d[v] = i
        # return should consider the last
        # non-repeated substring
        return max(res, len(s)-start)

這道求最長(zhǎng)無(wú)重復(fù)子串的題和之前那道 Isomorphic Strings 很類似泛源,屬于LeetCode的早期經(jīng)典題目,博主認(rèn)為是可以跟Two Sum媲美的一道題忿危。給了我們一個(gè)字符串俩由,讓我們求最長(zhǎng)的無(wú)重復(fù)字符的子串,注意這里是子串癌蚁,不是子序列幻梯,所以必須是連續(xù)的。我們先不考慮代碼怎么實(shí)現(xiàn)努释,如果給一個(gè)例子中的例子"abcabcbb"碘梢,讓你手動(dòng)找無(wú)重復(fù)字符的子串,該怎么找伐蒂。博主會(huì)一個(gè)字符一個(gè)字符的遍歷煞躬,比如a,b逸邦,c恩沛,然后又出現(xiàn)了一個(gè)a,那么此時(shí)就應(yīng)該去掉第一次出現(xiàn)的a缕减,然后繼續(xù)往后雷客,又出現(xiàn)了一個(gè)b,則應(yīng)該去掉一次出現(xiàn)的b桥狡,以此類推搅裙,最終發(fā)現(xiàn)最長(zhǎng)的長(zhǎng)度為3皱卓。所以說(shuō),我們需要記錄之前出現(xiàn)過(guò)的字符部逮,記錄的方式有很多娜汁,最常見(jiàn)的是統(tǒng)計(jì)字符出現(xiàn)的個(gè)數(shù),但是這道題字符出現(xiàn)的位置很重要兄朋,所以我們可以使用HashMap來(lái)建立字符和其出現(xiàn)位置之間的映射掐禁。進(jìn)一步考慮,由于字符會(huì)重復(fù)出現(xiàn)颅和,到底是保存所有出現(xiàn)的位置呢穆桂,還是只記錄一個(gè)位置?我們之前手動(dòng)推導(dǎo)的方法實(shí)際上是維護(hù)了一個(gè)滑動(dòng)窗口融虽,窗口內(nèi)的都是沒(méi)有重復(fù)的字符享完,我們需要盡可能的擴(kuò)大窗口的大小。由于窗口在不停向右滑動(dòng)有额,所以我們只關(guān)心每個(gè)字符最后出現(xiàn)的位置般又,并建立映射。窗口的右邊界就是當(dāng)前遍歷到的字符的位置巍佑,為了求出窗口的大小茴迁,我們需要一個(gè)變量left來(lái)指向滑動(dòng)窗口的左邊界,這樣萤衰,如果當(dāng)前遍歷到的字符從未出現(xiàn)過(guò)堕义,那么直接擴(kuò)大右邊界,如果之前出現(xiàn)過(guò)脆栋,那么就分兩種情況倦卖,在或不在滑動(dòng)窗口內(nèi),如果不在滑動(dòng)窗口內(nèi)椿争,那么就沒(méi)事怕膛,當(dāng)前字符可以加進(jìn)來(lái),如果在的話秦踪,就需要先在滑動(dòng)窗口內(nèi)去掉這個(gè)已經(jīng)出現(xiàn)過(guò)的字符了褐捻,去掉的方法并不需要將左邊界left一位一位向右遍歷查找,由于我們的HashMap已經(jīng)保存了該重復(fù)字符最后出現(xiàn)的位置椅邓,所以直接移動(dòng)left指針就可以了柠逞。我們維護(hù)一個(gè)結(jié)果res,每次用出現(xiàn)過(guò)的窗口大小來(lái)更新結(jié)果res景馁,就可以得到最終結(jié)果啦板壮。

這里我們可以建立一個(gè)HashMap,建立每個(gè)字符和其最后出現(xiàn)位置之間的映射裁僧,然后我們需要定義兩個(gè)變量res和left个束,其中res用來(lái)記錄最長(zhǎng)無(wú)重復(fù)子串的長(zhǎng)度,left指向該無(wú)重復(fù)子串左邊的起始位置的前一個(gè)聊疲,由于是前一個(gè)茬底,所以初始化就是-1,然后我們遍歷整個(gè)字符串获洲,對(duì)于每一個(gè)遍歷到的字符阱表,如果該字符已經(jīng)在HashMap中存在了,并且如果其映射值大于left的話贡珊,那么更新left為當(dāng)前映射值最爬。然后映射值更新為當(dāng)前坐標(biāo)i,這樣保證了left始終為當(dāng)前邊界的前一個(gè)位置门岔,然后計(jì)算窗口長(zhǎng)度的時(shí)候爱致,直接用i-left即可,用來(lái)更新結(jié)果res寒随。

這里解釋下程序中那個(gè)if條件語(yǔ)句中的兩個(gè)條件m.count(s[i]) && m[s[i]] > left糠悯,因?yàn)橐坏┊?dāng)前字符s[i]在HashMap已經(jīng)存在映射,說(shuō)明當(dāng)前的字符已經(jīng)出現(xiàn)過(guò)了妻往,而若m[s[i]] > left 成立互艾,說(shuō)明之前出現(xiàn)過(guò)的字符在我們的窗口內(nèi),那么如果要加上當(dāng)前這個(gè)重復(fù)的字符讯泣,就要移除之前的那個(gè)纫普,所以我們讓left賦值為m[s[i]],由于left是窗口左邊界的前一個(gè)位置(這也是left初始化為-1的原因,因?yàn)榇翱谧筮吔缡菑?開(kāi)始遍歷的),所以相當(dāng)于已經(jīng)移除出滑動(dòng)窗口了讹开。舉一個(gè)最簡(jiǎn)單的例子"aa"谁尸,當(dāng)i=0時(shí),我們建立了a->0的映射懦趋,并且此時(shí)結(jié)果res更新為1,那么當(dāng)i=1的時(shí)候,我們發(fā)現(xiàn)a在HashMap中但指,并且映射值0大于left的-1,所以此時(shí)left更新為0抗楔,映射對(duì)更新為a->1棋凳,那么此時(shí)i-left還為1,不用更新結(jié)果res连躏,那么最終結(jié)果res還為1

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末剩岳,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子入热,更是在濱河造成了極大的恐慌拍棕,老刑警劉巖晓铆,帶你破解...
    沈念sama閱讀 218,607評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異绰播,居然都是意外死亡骄噪,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,239評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門蠢箩,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)链蕊,“玉大人,你說(shuō)我怎么就攤上這事谬泌√显希” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 164,960評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵掌实,是天一觀的道長(zhǎng)陪蜻。 經(jīng)常有香客問(wèn)我,道長(zhǎng)贱鼻,這世上最難降的妖魔是什么囱皿? 我笑而不...
    開(kāi)封第一講書人閱讀 58,750評(píng)論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮忱嘹,結(jié)果婚禮上嘱腥,老公的妹妹穿的比我還像新娘。我一直安慰自己拘悦,他們只是感情好齿兔,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,764評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著础米,像睡著了一般分苇。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上屁桑,一...
    開(kāi)封第一講書人閱讀 51,604評(píng)論 1 305
  • 那天医寿,我揣著相機(jī)與錄音,去河邊找鬼蘑斧。 笑死靖秩,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的竖瘾。 我是一名探鬼主播沟突,決...
    沈念sama閱讀 40,347評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼捕传!你這毒婦竟也來(lái)了惠拭?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 39,253評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤庸论,失蹤者是張志新(化名)和其女友劉穎职辅,沒(méi)想到半個(gè)月后棒呛,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,702評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡域携,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,893評(píng)論 3 336
  • 正文 我和宋清朗相戀三年簇秒,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片涵亏。...
    茶點(diǎn)故事閱讀 40,015評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡宰睡,死狀恐怖蒲凶,靈堂內(nèi)的尸體忽然破棺而出气筋,到底是詐尸還是另有隱情,我是刑警寧澤旋圆,帶...
    沈念sama閱讀 35,734評(píng)論 5 346
  • 正文 年R本政府宣布宠默,位于F島的核電站,受9級(jí)特大地震影響灵巧,放射性物質(zhì)發(fā)生泄漏搀矫。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,352評(píng)論 3 330
  • 文/蒙蒙 一刻肄、第九天 我趴在偏房一處隱蔽的房頂上張望瓤球。 院中可真熱鬧,春花似錦敏弃、人聲如沸卦羡。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,934評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)绿饵。三九已至,卻和暖如春瓶颠,著一層夾襖步出監(jiān)牢的瞬間拟赊,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,052評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工粹淋, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留吸祟,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,216評(píng)論 3 371
  • 正文 我出身青樓桃移,卻偏偏與公主長(zhǎng)得像欢搜,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子谴轮,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,969評(píng)論 2 355

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