给定一个字符串 s
,请你找出其中不含有重复字符的 最长 子串的长度。
示例 1:
输入: s = "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc"
,所以其长度为 3。
这个题目的第一个想法就是直接两个for循环遍历所有的子串找到最长的那个,那这个题目就变得毫无意义这个时候我想到了如何判断一个数的所有位数是否是唯一的数字,比如123456789这个数。可以使用长度为10的数组去记录每个数字出现的次数。同理这个也是判断字符有无重复。可以定义一个长度为128的数组去记录字符出现的次数。
此时再加上滑动窗口的方法遍历,每次窗口扩大一点都将新的元素与窗口内的元素进行比对,那这样又会回到双循环,这个时候我们定义的数组就起了作用。如果我们已经计入了a这个元素在数组中索引值为a的ASCll码的下标对应的值应该是为1,所以若是再次遍历到了就可以很容易发现。
如下图:
1.初始状态为窗口内只有a一个元素接下来不断遍历一直向后添加元素,不断扩充右边界直至将a,b,c这三个元素全部计入此时计入这个子串的长度
2.更改状态此时遍历到了一个元素与窗口内的元素重复所以需要将旧的元素删除所以此时就需要更改左边界直至删除了与我新元素相同的元素(比如现在新的元素是a所以我需要不断更改左边界直至删除了旧元素a,因为此时的子串是也是无重复的,将这个子串的长度与之前的长度进行比较取最大的长度。
3.重复以上操作直至右边界到达数组的最右端
下列是代码实现:
int lengthOfLongestSubstring(char* s) {
int result =0; //定义一个用于比较的数
int left = 0; //定义左边界
int count[128]={}; //定义记录字符出现次数的数组
for(int right=0;s[right];right++){ //根据右边界遍历字符串
char c = s[right]; //取出字符
//判断该字符是否已经出现(因为初始化数组时所有值为)也可以写为count[c]
while(count[c]==1){
//若出现了不断删除左边界的元素直至删除旧元素
//只有这样做才能满足题目条件无重复
count[s[left++]] = 0;
}
count[c]=1; //记录元素
int length = right-left+1; //记录当前长度
result = result>length?result:length; //判断长度
}
return result;
}
下列是代码的实现示例:
int main(){
char *s = "abcabcbb";
int num = lengthOfLongestSubstring(s);
printf("结果为:%d",num);
return 0;
}
下列是完整代码:
#include<stdio.h>
int lengthOfLongestSubstring(char* s) {
int result =0; //定义一个用于比较的数
int left = 0; //定义左边界
int count[128]={}; //定义记录字符出现次数的数组
for(int right=0;s[right];right++){ //根据右边界遍历字符串
char c = s[right]; //取出字符
//判断该字符是否已经出现(因为初始化数组时所有值为)也可以写为count[c]
while(count[c]==1){
//若出现了不断删除左边界的元素直至删除旧元素
//只有这样做才能满足题目条件无重复
count[s[left++]] = 0;
}
count[c]=1; //记录元素
int length = right-left+1; //记录当前长度
result = result>length?result:length; //判断长度
}
return result;
}
int main(){
char *s = "abcabcbb";
int num = lengthOfLongestSubstring(s);
printf("结果为:%d",num);
return 0;
}
感谢你看到这里,若代码有误或是无法运行请留言