LeetCode(3) ---- Longest Substring Without Repeating Characters

Problem

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.

大致意思:給定一個(gè)字符串浊吏,找到其中最大不重復(fù)子串芙粱,返回其長(zhǎng)度。

My View

一開(kāi)始的思路就是暴力解決疆偿,兩個(gè)循環(huán)來(lái)檢查是否滿足條件朵栖,然后就有了下面的代碼

class Solution {
    public int lengthOfLongestSubstring(String s) {
        if(s.equals("")){
           return 0;    
        }else{
        int count;
        int ecount = 0;
        for(int i = 0;i<s.length(); i++){
            count = 1;
            for(int j = i+1; j < s.length(); j++){
              if(s.substring(i,j).contains(String.valueOf(s.charAt(j)))){
                  break; 
              }
                count++;
            }
         if(count > ecount){
             ecount = count;
         } 
        }
        return ecount;     
    }
  }
}

很可惜怜森,


得到了這樣的結(jié)果邮破,982/983邻吞,最后一組數(shù)據(jù)因?yàn)樘L(zhǎng)齿兔,規(guī)定時(shí)間耗盡萨螺,然后不符合題目要求。
第一反應(yīng)是HashMap愧驱,因?yàn)閯傋鲎鲞^(guò)的第一題優(yōu)解是采用HashMap的慰技,可是搞了半天還是搞不明白,對(duì)Hashmap了解甚少……感覺(jué)Java白學(xué)了组砚,挖個(gè)坑復(fù)習(xí)去吻商。

Solution

solution1

那么下面是官方的solution

To enumerate all substrings of a given string, we enumerate the start and end indices of them. Suppose the start and end indices are ii and jj, respectively. Then we have 0 \leq i \lt j \leq n0≤i<j≤n (here end index jj is exclusive by convention). Thus, using two nested loops with ii from 0 to n - 1n?1 and jj from i+1i+1 to nn, we can enumerate all the substrings of s.
To check if one string has duplicate characters, we can use a set. We iterate through all the characters in the string and put them into the set one by one. Before putting one character, we check if the set already contains it. If so, we return false. After the loop, we return true.

具體的意思就是建立一個(gè)雙層循環(huán),來(lái)取得子字符串糟红,然后通過(guò)檢查函數(shù)來(lái)檢查此字符串滿不滿足條件艾帐,而檢查函數(shù)的寫(xiě)法是通過(guò)一個(gè)set集合來(lái)儲(chǔ)存被比較值,然后不斷拿比較值來(lái)比較是否存在盆偿。

public class Solution {
    public int lengthOfLongestSubstring(String s) {
        int n = s.length();
        int ans = 0;
        for (int i = 0; i < n; i++)
            for (int j = i + 1; j <= n; j++)
                if (allUnique(s, i, j)) ans = Math.max(ans, j - i);
        return ans;
    }

    public boolean allUnique(String s, int start, int end) {
        Set<Character> set = new HashSet<>();
        for (int i = start; i < end; i++) {
            Character ch = s.charAt(i);
            if (set.contains(ch)) return false;
            set.add(ch);
        }
        return true;
    }
}

可以看到allUnique函數(shù)柒爸,建立一個(gè)數(shù)據(jù)集,然后在比較范圍內(nèi)事扭,沒(méi)有包含字符就添加進(jìn)結(jié)果集捎稚,有包含的話直接返回false。
然后通過(guò)max來(lái)找到最后的最大值。

由于用了三層循環(huán)今野,所以是O(n?3??)的復(fù)雜度葡公,結(jié)果自然是[Time Limit Exceeded]了。

solution2

然后官方第二種solution
Sliding Window(滑動(dòng)窗口)

The naive approach is very straightforward. But it is too slow. So how can we optimize it?

上來(lái)就來(lái)一句:明顯的嘲諷……

In the naive approaches, we repeatedly check a substring to see if it has duplicate character. But it is unnecessary. If a substring s_{ij}
?? from index ii to j - 1j?1 is already checked to have no duplicate characters. We only need to check if s[j] is already in the substring s_{ij}

那么這里的意思是条霜,如果我們已經(jīng)檢查了某個(gè)字串不含重復(fù)字符的話催什,就不用在多檢查一次了,而我們用雙層循環(huán)的時(shí)候宰睡,其實(shí)是對(duì)已經(jīng)檢查過(guò)的串又檢查一遍蒲凶。

By using HashSet as a sliding window, checking if a character in the current can be done in O(1).

這里就給出了解決方案,用一個(gè)HashSet集合來(lái)作為一個(gè)滑動(dòng)窗口來(lái)檢查字符串拆内,可以降低我們的復(fù)雜度豹爹,那么突破點(diǎn)也就在這。

A sliding window is an abstract concept commonly used in array/string problems.

那么滑動(dòng)窗口多用來(lái)解決一些數(shù)組或者字符串的問(wèn)題矛纹,是一個(gè)抽象的概念

Back to our problem. We use HashSet to store the characters in current window [i, j) (j ==i initially). Then we slide the index j to the right. If it is not in the HashSet, we slide j further. Doing so until s[j] is already in the HashSet. At this point, we found the maximum size of substrings without duplicate characters start with index ii. If we do this for all ii, we get our answer.

回到問(wèn)題中臂聋,我們用哈希集合來(lái)儲(chǔ)存一個(gè)[i,j)區(qū)間的子串作為一個(gè)窗口或南,然后我們移動(dòng)右邊值孩等,如果發(fā)現(xiàn)的新值不在集合里就接著找,直到找到一個(gè)在集合里已經(jīng)有的值采够,記錄下此時(shí)的不重復(fù)長(zhǎng)度肄方,那么接下來(lái)把窗口左值向右移動(dòng)就可以遍歷完所有的子串。從而最后得到我們的最大值蹬癌。

接下來(lái)代碼

public class Solution {
    public int lengthOfLongestSubstring(String s) {
       //取得字符串長(zhǎng)度 
       int n = s.length();
      //建立HashSet
        Set<Character> set = new HashSet<>();
        int ans = 0, i = 0, j = 0;
        
       //遍歷字符串
        while (i < n && j < n) {
            // try to extend the range [i, j]
           //如果數(shù)據(jù)集不包含查找到的新字符 
           //就把他放到集合里
           if (!set.contains(s.charAt(j))){
                set.add(s.charAt(j++));
                //返回可以找到的最大值
                ans = Math.max(ans, j - i);
            }
            else {
               //否則本次查找結(jié)束权她,窗口左邊向右移動(dòng)
                set.remove(s.charAt(i++));
            }
        }
        return ans;
    }
}

那么很顯然這個(gè)算法的復(fù)雜度是O(n),那么空間復(fù)雜度的話,是取決于Hash占用的逝薪,當(dāng)然也取決于字符串的長(zhǎng)度隅要。

在這里會(huì)發(fā)現(xiàn)Hash在解決數(shù)組或字符串問(wèn)題上很有用,完全可以替代兩層循環(huán)的復(fù)雜度董济,在下面官方還給了一個(gè)滑動(dòng)窗口改進(jìn)版步清,

public class Solution {
    public int lengthOfLongestSubstring(String s) {
        int n = s.length(), ans = 0;
        Map<Character, Integer> map = new HashMap<>(); // current index of character
        // try to extend the range [i, j]
        for (int j = 0, i = 0; j < n; j++) {
            if (map.containsKey(s.charAt(j))) {
                i = Math.max(map.get(s.charAt(j)), i);
            }
            ans = Math.max(ans, j - i + 1);
            map.put(s.charAt(j), j + 1);
        }
        return ans;
    }
}

太深?yuàn)W,慢慢理解吧虏肾。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末廓啊,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子封豪,更是在濱河造成了極大的恐慌谴轮,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,968評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件吹埠,死亡現(xiàn)場(chǎng)離奇詭異第步,居然都是意外死亡疮装,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)雌续,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人胯杭,你說(shuō)我怎么就攤上這事驯杜。” “怎么了做个?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,220評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵鸽心,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我居暖,道長(zhǎng)顽频,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,416評(píng)論 1 279
  • 正文 為了忘掉前任太闺,我火速辦了婚禮糯景,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘省骂。我一直安慰自己蟀淮,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布钞澳。 她就那樣靜靜地躺著怠惶,像睡著了一般。 火紅的嫁衣襯著肌膚如雪轧粟。 梳的紋絲不亂的頭發(fā)上策治,一...
    開(kāi)封第一講書(shū)人閱讀 49,144評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音兰吟,去河邊找鬼通惫。 笑死,一個(gè)胖子當(dāng)著我的面吹牛混蔼,可吹牛的內(nèi)容都是我干的讽膏。 我是一名探鬼主播,決...
    沈念sama閱讀 38,432評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼拄丰,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼府树!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起料按,我...
    開(kāi)封第一講書(shū)人閱讀 37,088評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤奄侠,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后载矿,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體垄潮,經(jīng)...
    沈念sama閱讀 43,586評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡烹卒,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了弯洗。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片旅急。...
    茶點(diǎn)故事閱讀 38,137評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖牡整,靈堂內(nèi)的尸體忽然破棺而出藐吮,到底是詐尸還是另有隱情,我是刑警寧澤逃贝,帶...
    沈念sama閱讀 33,783評(píng)論 4 324
  • 正文 年R本政府宣布谣辞,位于F島的核電站,受9級(jí)特大地震影響沐扳,放射性物質(zhì)發(fā)生泄漏泥从。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評(píng)論 3 307
  • 文/蒙蒙 一沪摄、第九天 我趴在偏房一處隱蔽的房頂上張望躯嫉。 院中可真熱鬧,春花似錦杨拐、人聲如沸和敬。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,333評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)昼弟。三九已至,卻和暖如春奕筐,著一層夾襖步出監(jiān)牢的瞬間舱痘,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,559評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工离赫, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留芭逝,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,595評(píng)論 2 355
  • 正文 我出身青樓渊胸,卻偏偏與公主長(zhǎng)得像旬盯,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子翎猛,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評(píng)論 2 345

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