題目描述
給定一個字符串,請你找出其中不含有重複字符的 最長子串 的長度。
- 示例 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;
}
};