Leetcode#3 最大無重複字符子串

題目描述

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

  • 示例 1:
    輸入: “abcabcbb”
    輸出: 3
    解釋: 因爲無重複字符的最長子串是 “abc”,所以其長度爲 3。
  • 示例 2:
    輸入: “bbbbb”
    輸出: 1
    解釋: 因爲無重複字符的最長子串是 “b”,所以其長度爲 1。
  • 示例 3:
    輸入: “pwwkew”
    輸出: 3
    解釋: 因爲無重複字符的最長子串是 “wke”,所以其長度爲 3。
    請注意,你的答案必須是 子串 的長度,“pwke” 是一個子序列,不是子串。

算法思路

首先,可以用暴力的方法來解決這個問題,依次遍歷所有可能的子串,但是最後一個樣例會超時,因此要去除其中一些冗餘的情況。
算法步驟如下:
(1)設下標i爲當前查詢字符串的末尾字符,直到i=s.size(),循環結束。
(2)設下標j爲從當前查詢字符串開始位置的下標s_index到下標爲i的末尾字符的下標,依次遍歷子串,通過IsUnique函數檢查s[i]是否等於s[s_index~(i-1)]子串中的某一元素。若有重複元素,則直接返回該重複字符的下標i;若無重複元素,則返回-1;
(3)返回標誌flag等於-1,則長度加1;否則,說明以s_index爲起始位置、以i-1爲結束位置的子串中無重複字符,其長度等於子串的尾端下標i減去返回的重複字符的下標flag,即len = i - flag,同時,flag位置之前無重複子串,flag與i爲重複子串,因此再重複檢測i後的元素與flag之前的元素是否相等是冗餘的工作,無需用s_index++語句來循環遍歷以i+1爲結尾位置最長子串的開始位置,而可直接用s_index=flag+1來優化該程序
(4)用max_len存最大無重複字符子串的長度,每次子循環遍歷結束進行判斷,更新並記錄最大長度。

代碼實現

初步實現代碼如下,但其結果卻不盡如人意,因爲不停地調用IsUnique函數,將字符串s作爲參數傳遞,會消耗大量內存和時間。

class Solution {
public:
    int IsUnique(string s, int start, int pre){
        for(int i = start; i < pre; i++){
            if( s[pre] == s[i] ) return i;
            else continue;
        }
        return -1;
    }
    int lengthOfLongestSubstring(string s) {
        if(s == "") return 0;
        int len = 1;
        int max_len = 1;
        int s_index = 0;
        int flag;
        for(int i = 1; i < s.size(); i++){
            flag = IsUnique(s, s_index, i);
            if(flag == -1){
                len ++;
            }
            else{
                len = i - flag;
                s_index = flag + 1;
            }
            if(max_len < len) max_len = len;
        }
        return max_len;
    }
};

因此,將判斷當前字符s[i]是否與子串s[s_index~(i-1)]有重複子串的函數IsUnique拆出,放入主函數中,代碼執行速度提升很大。

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        if(s == "") return 0;
        int len = 1;
        int max_len = 1;
        int s_index = 0; //下邊
        int i,j;
        for( i = 1; i < s.size(); i++){
            for( j = s_index; j < i; j++){
                if (s[j] == s[i]){
                    s_index = j + 1;
                    len = i - j;
                    break;
                } 
                else continue;
            }
            if(j == i){
                len ++;
            }
            if(max_len < len) max_len = len;
        }
        return max_len;
    }
};

以上代碼中仍然不夠簡潔,如果s[i]與子串s[s_index~(i-1)]中無重複字符,無需在逐字符判斷完後疊加len,即if(j == i){len ++;},若無重複元素,則長度應等於i - s_index+1.

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        if(s == "") return 0;
        int max_len = 1;
        int s_index = 0;
        int i,j;
        for( i = 1; i < s.size(); i++){
            for( j = s_index; j < i; j++){
                if (s[j] == s[i]){
                    s_index = j + 1;
                    break;
                } 
                else continue;
            }
            if(max_len < i-s_index+1 ) max_len = i-s_index+1;
        }
        return max_len;
    }
};

運行結果

運行時間運行性能

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