給定一個僅包含英文字元的字串,找出其中第一個出現的最長不含重複字元的子串。要求時間複雜度 O(n),空間複雜度 O(1)(固定 256 字元集)。
[CurrentStart, i]。hash[256] 記錄每個字元最近一次出現的索引,初始為 -1。str[i]:
hash[str[i]] < CurrentStart,說明該字元在當前窗口未出現 → 擴展窗口,更新 hash[str[i]] = i。CurrentLength = i - CurrentStart,若大於歷史最大長度,更新 MaxStart、MaxEnd。CurrentStart = hash[str[i]] + 1。hash[str[i]] = i。char* GetMaxSubStr(char* str) {
int hash[256];
for (int i = 0; i < 256; ++i) hash[i] = -1;
int CurrentStart = 0, MaxStart = 0, MaxEnd = 0;
int strLen = strlen(str);
for (int i = 0; i < strLen; ++i) {
if (CurrentStart > hash[str[i]]) {
hash[str[i]] = i; // 無重複,擴展窗口
} else {
int CurrentLength = i - CurrentStart;
if (CurrentLength > MaxEnd - MaxStart) {
MaxEnd = i;
MaxStart = CurrentStart;
}
CurrentStart = hash[str[i]] + 1; // 縮減窗口,跳過重複字元
hash[str[i]] = i;
}
}
// 處理遍歷結束後最後一個窗口
if (strLen - CurrentStart > MaxEnd - MaxStart) {
MaxEnd = strLen;
MaxStart = CurrentStart;
}
int MaxLength = MaxEnd - MaxStart;
char* reStr = (char*)malloc(MaxLength + 1);
reStr[MaxLength] = '\0';
memcpy(reStr, str + MaxStart, MaxLength);
return reStr; // 呼叫端需 free()
}
hash 為 -1:表示字元尚未出現,配合 CurrentStart 初始為 0,首次遇到任意字元時 CurrentStart (0) > hash[c] (-1) 成立,正確判定為「無重複」。CurrentStart = hash[str[i]] + 1 確保新窗口不包含重複字元,且保留盡可能長的尾部。malloc 分配的記憶體,使用者必須 free();若不想動態分配,可改為填充呼叫端提供的緩衝區。int 陣列 + 少量變數。原文作者後續發現原版在處理字串尾部無重複情況有誤,補充了迴圈後的檢查邏輯(見上方完整實作)。這正是「測試驅動開發」的典型案例:沒有測試用例保證的程式碼只是無序字元。