Leetcode C++《热题 Hot 100-23》3.无重复字符的最长子串
热题Hot 100的easy题目已经结束,开始medium题目,加油呀
- 题目
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: “abcabcbb”
输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。
示例 2:
输入: “bbbbb”
输出: 1
解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。
示例 3:
输入: “pwwkew”
输出: 3
解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。
请注意,你的答案必须是 子串 的长度,“pwke” 是一个子序列,不是子串。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/longest-substring-without-repeating-characters
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
- 思路
- 方案1:暴力遍历所有长度的子串,时间复杂度是n*n(所有长度子串的数目) *n(检查子串有没有重复map),空间复杂度为1
- 方案2:需要降低时间复杂度,用两个指针i和j,i-j之间的substr有map来记录出现过的char,从左向后遍历,如果字符没出现过j++,如果字符出现过,那就i++判断该字符是不是出现过,每次更新i和j,都需要更新全局的maxLenghth,时间复杂度为n,空间复杂度为n
- 方案3:可以对方案2进行优化,如果字符出现过,i可以变成j+1,j字符出现过的情况下maxLength肯定会减小,则可以直接跳过这部分
- 需要了解一下:子序列和子串是不一样的,子序列不要求连续,子串是必须连续的
- 代码
class Solution {
public:
int lengthOfLongestSubstring(string s) {
if (s.length() == 0)
return 0;
map<char, int> mark;
int maxLength = 0;
int left = 0;
int right = 0; //[left, right]
mark.insert(make_pair(s[0], 1));
maxLength = 1;
map<char, int>::iterator it;
for (int i = 1; i < s.length(); i++) {
it = mark.find(s[i]);
if (it == mark.end()) {
right = i;
mark.insert(make_pair(s[i], 1));
maxLength = max(maxLength, right-left+1);
} else {
//如果子串有,那就要把子串删除,直到把right加进来,这期间不用更新maxLength,因为它的值要么不变要么减小
//方案3:这种情况可以直接更新i=j+1,因为这部分不会影响到maxLength
while (left <= right) {
mark.erase(s[left]);
if (s[i] == s[left]) {
left++;
right = i;
mark.insert(make_pair(s[i], 1));
break;
}
left++;
}
}
}
return maxLength;
}
};