描述:
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: s = "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例 2:
输入: s = "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
示例 3:
输入: s = "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
示例 4:
输入: s = ""
输出: 0
思路:
子串问题,最常用的方法就是滑动窗口,本题就是滑动窗口的典型应用,直接上代码
/*
* @lc app=leetcode.cn id=3 lang=cpp
*
* [3] 无重复字符的最长子串
*/
// @lc code=start
class Solution {
public:
int lengthOfLongestSubstring(string s) {
//使用滑动窗口
unordered_map<char, int> window;
int left = 0;
int right = 0;
int length = 0;
int result = 0;
while (right < s.size()) {
char tmp = s[right];
if((window.find(tmp) != window.end()) && window[tmp] >= left) {
left = window[tmp] + 1;
length = right - left;
}
window[tmp] = right;
right++;
length++;
result = max(length, result);
}
return result;
}
};
// @lc code=end
也有网络上所谓的滑动窗口框架,这里也套用框架,写一版
首先,框架如下
/*滑动窗口框架*/
void slidingWindow(string s) {
//定义窗口
unordered_map<char, int> window;
//窗口的左右边界
int left = 0, right = 0;
while (right < s.size()) {
// c 是将移入窗口的字符
char c = s[right];
// 增大窗口
right++;
// 进行窗口内数据的一系列更新
...
/*** debug 输出的位置 ***/
// 注意在最终的解法代码中不要 print
// 因为 IO 操作很耗时,可能导致超时
printf("window: [%d, %d)\n", left, right);
/********************/
// 判断左侧窗口是否要收缩
while (window needs shrink) {
// d 是将移出窗口的字符
char d = s[left];
// 缩小窗口
left++;
// 进行窗口内数据的一系列更新
...
}
}
}
套用上面的框架,每次只需要编写...省略部分的逻辑就可以,就本题
/*
* @lc app=leetcode.cn id=3 lang=cpp
*
* [3] 无重复字符的最长子串
*/
// @lc code=start
class Solution {
public:
int lengthOfLongestSubstring(string s) {
//使用滑动窗口
unordered_map<char, int> window;
int left = 0;
int right = 0;
int result = 0;
while (right < s.size()) {
char tmp1 = s[right];
right++;//右侧扩大边界
window[tmp1]++;
while (window[tmp1] > 1) {
//大于1说明窗口中有重复的元素,需要缩小窗口
char tmp2 = s[left];
left++;
window[tmp2]--;
}
result = max(result, right - left);
}
return result;
}
};
// @lc code=end