题目描述
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
- 示例 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;
}
};