题目
给定一个字符串 s ,请你找出其中不含有重复字符的最长子串的长度。
示例 1:
输入: s = “abcabcbb”
输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。
示例 2:
输入: s = “bbbbb”
输出: 1
解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。
示例 3:
输入: s = “pwwkew”
输出: 3
解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。
请注意,你的答案必须是 子串 的长度,“pwke” 是一个子序列,不是子串。
提示:
0 <= s.length <= 5 * 104
s 由英文字母、数字、符号和空格组成
代码
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define MAX(a,b) (a > (b) ? a : (b))
int lengthOfLongestSubstring(char* s) {
// ASCII table has 128 elements.
bool table[128] = {};
int left = 0;
int maxLen = 0;
for (int right = 0; right < strlen(s); right++) {
char c = s[right];
// if this character exit in the table, all character before
// it should be remove in window.
// Use while loop to lacate the duplicate charater in table.
while (table[c]) {
table[s[left]] = false;
left++;
}
// after remove the c in table, re-add it, which seen as
// move right.
table[c] = true;
maxLen = MAX(maxLen, right - left + 1);
}
return maxLen;
}
int main() {
char s[] = "abcadqw";
int res = lengthOfLongestSubstring(s);
printf("%d", res);
return 0;
}
分析
暴力解法
题目如果用经典的双for循环去解,对于abcadqw
,模拟执行过程:
a
要和b
,c
,a
逐一比较,此时得到abc
是无重复子串,abca
出现了字符a
重复。- 之后移动,从
b
出发进行判断,和c
,a
,d
…比较,最后得到无重复子串
在这个过程中,对第一个a
进行比较的时候,我们其实已经得到a
并不和bc
重复。
即abc
子串是无重复子串,bca
自然也是。那么在a
出现重复时,我们下一步就可以直接从d
开始判断即可。也就是双指针了。
双指针
使用双指针进行处理的时候,left
在出现重复字符的时候移动,right
是每次都移动一步。
right
每次移动一步好实现,for循环即可。但是left
如何移动呢?
还是abca
这个字符串,left
在a
重复之后移动到了b
。但是不能想当然的认为在重复之后left
加1。
需要思考清楚双指针优化的是哪一部分。如果字符串efabca
在出现重复的时候,left
移动到的位置是b
,也就是left
要不断增加,直到找到重复字符a
,即使用while循环实现。