leetcode刷題之無重複的最長子串

題目要求:

        給定一個字符串,找出不含有重複字符的 最長子串 的長度。

示例:

給定 "abcabcbb" ,沒有重複字符的最長子串是 "abc" ,那麼長度就是3。

給定 "bbbbb" ,最長的子串就是 "b" ,長度是1。

給定 "pwwkew" ,最長子串是 "wke" ,長度是3。請注意答案必須是一個子串"pwke" 是 子序列 而不是子串。

思路:

    我看見這道題目的第一感覺,就是從頭遍歷過來,將之前遍歷的一小段沒有重複字符的字符串存起來,如果出現新的字符串,就開闢一個新的字符串,進入下一不重複字符的字符串存儲。

    乍一看好像思路不錯沒有什麼遺漏。但是自信想象就會發現,如果我在遇到新的字符串的時候,就要開始在容器中新建一個字符的話,最後得到的不重複字符串肯定不對。比如abad,按照我剛纔的思路會得到ab,ad兩個字符串。但是正確的答案應該得到ab,bad!所以我需要做另外的處理來解決這個問題。

    我選擇的解決方案是在遍歷的過程中遇到新的字符串的時候,新建一個StringBuffer對象(因爲避免內存問題,所以選擇的StringBuffer或StringBuilder)。同時會將list中當前的StringBuffer對象取出來,截取與當前遍歷的字符相同的字符之後的所有字符,拼接到新建的StrngBuffer中。

    如果就可以獲得各個沒有重複字符串的 字符串StringBuffer的list集合。之後再排序選取最長字符串的即可獲得結果。

    如下是鄙人寫的代碼:

    public static int lengthOfLongestSubstring(String s) {
        if(s == null || s.length()==0)
            return 0;
        List<StringBuffer> list = new ArrayList<StringBuffer>();
        list.add(new StringBuffer());
        int index = 0;
        for(int i = 0;i<s.length();i++){
            String word = String.valueOf(s.charAt(i));

            //如果不包含 則可以拼接到list中
            if(!list.get(index).toString().contains(word)){
                list.get(index).append(word);
            }else{
                //發現重複字符串,需要新增元素,並且將前面不重複的部分拷貝過來
                index++;
                list.add(new StringBuffer(word));
                int indexOfWord = list.get(index-1).toString().indexOf(word);//前一個字符串該字出現的位置
                list.get(index).insert(0,list.get(index-1).substring(indexOfWord+1,list.get(index-1).length()));
            }

        }
        List<Integer> nums = new ArrayList<Integer>(list.size());
        for(int i = 0 ; i<list.size() ; i++){
            nums.add(list.get(i).toString().length());
        }
        Collections.sort(nums);
        return  nums.get(nums.size()-1);
    }

    下面是大神寫的代碼:

    public static int lengthOfLongestSubstring2(String s) {
        int[] list = new int[256]; // 初始化asc碼數的字符數值,都默認爲 -1
        int previous = -1, right = 0, max_len = 0;
        for(int i=0;i<list.length;i++){
            list[i]=-1;
        }
        //進行遍歷,每往右走一個字符,right就增加一,代表着第幾個字符。
        //如果出現重複的字符,那麼當前的 list[(int)c] 的值就會>-1(出現過的字符的值爲對應right值,即第幾個)
        //同時precious也一直保持着最近出現的 重複字符的上此次出現的 座標
        //因此,每次出現重複字符,並且重複字符的座標在previous之後的,這可以表示爲在之後出現了重複字符串,
        // 同時記錄該字符串起始位置 previous = list[(int)c] (該字符串結束位置爲list[(int)c] = right++)
        //Math.max(max_len, right - previous) 一直保持着最長字符串的長度
        while(right<s.length()){
            char c = s.charAt(right);
            if(list[(int)c] > previous)
                previous = list[(int)c];
            max_len = Math.max(max_len, right - previous);
            list[(int)c] = right++;
        }
        return max_len;
    }
可見大神代碼多麼簡介,並且少了很多不必要的過程。

若有不足,還望指正,大家一起學習,共勉!


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章