问题描述:给定一个字符串 s
,请你找出其中不含有重复字符的 最长子串 的长度。
示例1:
输入:s = "abcabcbb"
输出:3
解释:因为无重复字符的最长字串是是
"abc",所以其
长度为 3。
示例2:
输入:s = "bbbbb"
输出:1
解释:因为无重复字符的最长字串是是
"b",所以其
长度为 1。
示例3:
输入:s = "pwwkew"
输出:3
解释:因为无重复字符的最长子串是
"wke"
,所以其长度为 3。 请注意,你的答案必 须是 子串 的长度,"pwke"
是一个子序列,不是子串。
示例4:
输入:s = ""
输出:0
解题思路:这道题的目标是找出一串字符串中的最长子串,并且该子串必须不包含重复字符,而且这个子串必须是原字符串中连续的一部分(见示例3中的解释说明)。这道题明显可以采用暴力破解,多重循环遍历字符串,找出最长子串,但是这种方法显然时间复杂度会很高。初学者出于解决问题的角度可以这样做,但是对于有一定基础的不太建议采用暴力破解法。
对于这类需要多次遍历字符串的我们采用双指针解法,设定指针遍历条件以降低时间复杂度。
接下来我们用最简单易懂的图解法来讲解本题的解法:
我们对于子串: S = “abcecbca” 求其最长子串。
其中字符串变量str用来存储当前更新的字符串,maxlen用来存储当前最长无重复子串的长度。
初始时状态如下:开始指针i指向字符串的第二个字符,指针j指向str字符串的初始位置,大致思路为: 判断从当前j指针位置到当前i指针位置是否存在相同字符。若不存在,则指针i继续依序遍历字符串S,j回到str子串的初始位置;若存在,则将str字符串的初始位置指向重复字符的下一个字符,且本次比较遍历结束,i继续后移,j指向新的str字符串的初始位置。重复上述步骤,直至指针i遍历完整个字符串,返回最长无重复子串的长度。
图1
图2
图3
图4
图5
图6
图7
int lengthOfLongestSubstring(char * s){
int strLen = strlen(s);
int maxLen = 1;
int count ;
char *str = s;
int i,j;
int k = 0;
if(strLen == 0)//字符串为空串
{
return 0;
}
for(i=1;i<strLen;i++)//strLen是指字符串的长度,同时也是字符数组的最后一个字符的下一位。
{
count = 1; //字符串每次比较,count重新计数
for(j=0;j<i-k;j++)//i-k是新串的长度,同时也是新的字符数组的最后一个字符的下一位。
{
if(s[i]==str[j])
{
str = str+j+1;//重复的话,str指向重复字符的下一个字符
k = k+j+1;//k记录str共向后移动的字符数//向后移动的个数==去掉的字符个数
break; //str成为一个新串,重新开始比较
}else
{
count++; //不重复的情况时,计数值++
}
}
maxLen = maxLen>count?maxLen:count;//求最大字符长度//跳出for循环就意味着串比较结束
}
return maxLen;
}