1. 程式人生 > >c 求字串內無重複字元的最長子串

c 求字串內無重複字元的最長子串

  • 題目描述
    這裡寫圖片描述

  • 分析
    根據題意,最直接暴力的一種方法就是把所有子串都遍歷一遍,選出沒有重複字元且最長的子串即為結果。注意,本題只需要輸出最長子串的長度即可,無需內容。

  • 初版程式碼

int lengthOfLongestSubstring(char* s) {
    int len=strlen(s);
    int count=0;
    bool isOk=true;
    char *tempS;
    tempS=(char *)malloc(len);

    int longLastIndex=0;  //用來輸出最長子串的,但本題中無需用到它
    int longLenth=0
; for(int i=0;i<len;){ isOk=true; for(int j=0;j<count;j++){ if(tempS[j]==s[i]){ isOk=false; break; } } if(isOk){ tempS[count++]=s[i++]; if(i==len&&longLenth<count){ longLastIndex=i; longLenth=count
; } } else{ if(longLenth<count){ longLastIndex=i; longLenth=count; } i=i-count+1; count=0; } } return longLenth; }
  • 改進優化
    上述程式碼的實現就如分析裡所說,遍歷了所有子串來找結果。事實上,做了很多重複性的工作,比如說字串“abcabcbb”,當第四位‘a’字元不符合時,又從第2位(i-count+1)字元‘b’開始找,但其實我們在上一輪的時候,就已經比較過‘b’和‘c’了。針對此,我們可以得到更高效的程式碼,如下:
int lengthOfLongestSubstring(char* s) {
    int len=strlen(s);
    int count=0;
    int start=0;   //記錄新子串的起始位置
    bool isOk=true;
    //char *tempS;
    //tempS=(char *)malloc(len);     無需額外的陣列來儲存

    int longLastIndex=0;
    int longLenth=0;

    for(int i=0;i<len;i++){
        isOk=true;
        for(int j=0;j<count;j++){
            if(s[j+start]==s[i]){     //改動處
                isOk=false;
                start=j+start+1;             //改動處
                break;
            }

        }
        if(isOk){
            count++;
            if(i==len-1&&longLenth<count){
                longLenth=count;
            }
        }
        else{
            if(longLenth<count){
                longLenth=count;
            }
            count=i-start+1;   //改動處

        }
    }

    return longLenth;
}

該優化的核心思想是用一個start變數記錄下發生不滿足條件(即子符相同的)位置,那麼從start位置到達當前i變數所在的位置之間的子符,便是上一輪匹配中,滿足條件的子符,無需再回溯,直接記下其個數再接著匹配就好。