请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字符串的长度。
示例 1:
输入: "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例 2:
输入: "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
示例 3:
输入: "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
思路: 利用双指针,并开辟一个数组,对每个字符的出现进行统计,当字符出现次数大于1时,重新开始统计,直到遍历完字符串
前指针prev,后指针cur,prev不动,cur向后走,边走边统计字符个数,统计方法:arr[*cur]++。当发现某个字符个数大于1时,计算该段子串长度: cur-prev。随后prev要指向该段子串中与 *cur相同的字符的后面一个位置,再继续进行统计
以字符串"pwwkew"为例(图中手误arr多弄了个’w’的统计):
第一步:先将’p’统计为1,cur指向’w’,prev指向第一个字符’p’,将’w’的数量加1,‘p’ != ‘w’,cur向后走
第二步:cur指向’w’,判断’w’的个数已经>1了,计算该段字符串长度为cur - prev = 2,prev指向"pw"字符串的’w’的后面那个位置
prev改变位置,将’p’, 'w’的个数置0,再把cur指向的元素置1,从该位置开始统计,cur向后走
第三步:cur指向’k’,将 'k’的个数加1,cur向后走
第四步:cur指向’e’,将’e’的个数加1,cur向后走
第五步:
cur指向’w’,将’w’的个数加1,'w’的个数已经超过1了,计算长度:cur - prev = 3,更新最大长度为3,prev跳到"wke"中’w’的后面,cur向后走,重新进行统计
此时cur已经遍历完字符串了,再统计一次长度cur - prev = 3,不用更新,所以最大长度就为3
记得开辟一个128大小的arr来统计字符,因为远不止小写字母需要统计👀:
代码:
int lengthOfLongestSubstring(char* s){
if (*s == '\0')//空字符串
return 0;
int *judge = (int*)calloc(127, sizeof(int));//并不只有小写字母,所有字符都可能出现
judge[*s] = 1;//先统计首字符
int maxlength = 1;//最小长度为1,所以先把最大长度置为1
char*prev = s;
char*cur = s + 1;//sur直接指向第二个字符
while (*cur != '\0')
{
judge[*cur]++;//统计该字符
if (judge[*cur] > 1)//有重复的字母
{
if (maxlength < (cur - prev))//更新最大长度
{
maxlength = cur - prev;
}
while (*prev != *cur)//找到中间这串中与*cur相同的那个字符的位置
{
//把该位置之前的字符统计置为0
judge[*prev] = 0;
prev++;
}
//找到之后再++,跳过这个位置
prev++;
judge[*cur] = 1;//并把当前元素重新统计为1,重新向后计算
}
cur++;
}
if (maxlength < (cur - prev))//当cur指向'\0'时,也要再进行最后的统计
{
maxlength = cur - prev;
}
return maxlength;
}