给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: “abcabcbb”
输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。
示例 2:
输入: “bbbbb”
输出: 1
解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。
示例 3:
输入: “pwwkew”
输出: 3
解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。
请注意,你的答案必须是 子串 的长度,“pwke” 是一个子序列,不是子串。
我的c++实现
class Solution {
public:
int lengthOfLongestSubstring(string s) {
for(int i=0;i<s.length();i++){
char first=s.at(i);
int p=s.find(first,i+1);
if(p==-1)
continue;
int k=lengthOfLongestSubstring(s.substr(0,p));
int t=lengthOfLongestSubstring(s.substr(i+1,s.length()-i-1));
if(k>=t){
return k;
}else{
return t;
}
}
return s.length();
}
};
emm 虽然问题解决了 但是使用的是递归 执行时间和内存消耗都贼大
刚刚看了题解 使用的是滑动窗口 明天决定实现一下它
昨天看的题解,今天去找居然找不到了 2333,凭着依稀的记忆实现了一下
class Solution {
public:
int lengthOfLongestSubstring(string s) {
int i,j;
int result=0;
for(i=0,j=0;j<s.length();){
if(s.find(s.at(j),i)==j){
result=max(result,j-i+1);
j++;
}else{
i++;
}
}
return result;
}
};
滑动窗口算法需要两个变量,i、j,分别用来记录当前窗口的起始位置和结束位置。
循环中首先判断 j 所在位置的元素从 i 开始有没有重复的,如果没有重复的,那么返回值为j,如果有重复的那么 i 向右移动再继续判断。
result 用来计算循环过程中 i 与 j 的最大间距;
这里要了解两个函数
s.at(j) 指 返回 s 中 j 所在位置的元素
s.find(s.at(j),i) 指 从 s 的第 i 个位置开始查找元素 s.at(j),返回第一个匹配上的元素下标,找不到返回 -1。
画图说明一下:
- 首先 i、j 都指向a,由于没有重复的字母,j 一直++
- 当 j 指向下标为 3 的 a 时,s.find(s.at(j),i)返回的是 0 ,因为从 0 起第一个 a 的位置为0,说明 i 与 j 之间有重复的字母,i 向后移动一位
在另一种假设下:
当 i = 0,j = 4时,发现s.find(s.at(j),i)不等于 j ,i 向后移动一位。
这时 i = 1,j = 4,s.find(s.at(j),i)仍然不等于 j,i 继续向后移动。
在这个例子中 result 的值记录为 4 ,因为 i 与 j 的最大间距是 i = 0,j = 3时 ,不管后面怎么变,result 不变。