给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: “abcabcbb”
输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。
示例 2:
输入: “bbbbb”
输出: 1
解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。
示例 3:
输入: “pwwkew”
输出: 3
解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。
请注意,你的答案必须是 子串 的长度,“pwke” 是一个子序列,不是子串。
解析
当然暴力求解法是可以的,对这个字符串的首尾都进行遍历,并且判断每个子串是否无重复,此时的时间复杂度为O(n^3),提交后超出时间限制,所以要进行优化,
class Solution {
public:
int lengthOfLongestSubstring(string s) {
int maxlen=1;
if(s=="") //为空时判断
maxlen=0;
for(int i=0;i<s.length();i++)
for(int j=i+1;j<s.length();j++)
if(ISUnique(s,i,j))
maxlen=maxlen<j-i+1?j-i+1:maxlen;
else
break;
return maxlen;
}
bool ISUnique(string s,int start,int end) {
vector<char> charset;
for(int i=start;i<=end;i++){
if(find(charset.begin(),charset.end(),s[i])!=charset.end())
return false;
charset.push_back(s[i]);
}
return true;
}
};
优化一
对字符串首尾进行遍历时,遇到子串重复时,则进行下一个子串的检测,这时对下一个子串的选取就很重要了,去除一些冗余的选择,可以提高我们的运行速度。
比如我们的头部遍历到i、尾部遍历到j时,发现它不是无重复字符串,换句话说就是第j个字符和前面i~j的字符里的某个重复了,那此时,将头部索引+1即变成i+1,是多余的,因为这个重复的字符在i-j之间,只要不是i,那此时的字符串依旧是重复的。
所以我们选取下一个待检查的字符串可选择i等于和j重复的那个字符的位置的后一个,j从当前j开始,不用从i+1开始重新遍历
优化二
对子串检查是否重复可利用map,构建哈希表,提高搜索速度
class Solution {
public:
int lengthOfLongestSubstring(string s) {
int maxlen = 0;
int j = 0,i=0;
if (s == ""){
maxlen = 0;
return 0;
}
map<char, int> map1;
while (i<s.length() -maxlen&& j < s.length())
if (map1.find(s[j]) == map1.end() || (map1.find(s[j]) != map1.end()&& map1.find(s[j])->second < i)){
map1[s[j]] = j;
maxlen = maxlen < j - i + 1 ? j - i + 1 : maxlen;
j++;
}
else{
i = map1.find(s[j])->second + 1;
}
return maxlen;
}
};