1. 题目描述
难度:中等
2. 题目分析
这道题目是一道中等难度的题目,我们需要知道的有一点:
- 字符串中有包括空字符的所有字符,不止英文字母
这一点很重要,因为在刚接触这道题的时候,很容易当成字符串中只有英文字符,这在使用ASCII码的时候会有麻烦。
这道题当然可以使用暴力穷举法,求出所有可能的字符串,并选出合适的字符串并输出最大长度,这么做的话时间复杂度太高了。有一种方法可以使时间复杂度为O(n),那就是双指针法。
- 双指针法
定义两个指针,一个头指针用来指向字符串的头,一个指针用来滑动。申请一个128个元素的数组空间,用来表示当前字符串是否有重复的元素。为什么大小为128?因为根据ASCII码表,一共有128个元素(包含空元素)。举个例子:如果滑动指针指向的是字符‘a’,该字符对应的ASCII码表为97,所以在新建的数组的下标为97的空间存储为1。滑动指针滑动的时候,一直判断指向的元素所对应的新建数组中的元素是否为1,如果是1那么表示该元素在之前已经初出现,如果是0,表示该元素在之前并没有出现。具体代码见第三节。
3. C语言实现
代码如下:
int lengthOfLongestSubstring(char * s){
/***
参数列表:
i:滑动指针; index:头指针; len:字符串长度;
label:字符对应的下标; max: 字符串长度最大值
count: 滑动过程中字符串的长度
***/
int i, index, len, max, label, count;
// 初始化变量以及申请数组空间
max = 0;
count = 0;
index = 0;
len = strlen(s);
int *temp = (int *)malloc(sizeof(int)*128);
// 开始循环
for(i = 0; i < len; i++){
label = (int)(s[i]);
// 如果字符之前没有出现
if(temp[label] != 1){
// 在相应的位置上置1,长度加一
temp[label] = 1;
count++;
}
// 如果字符在之前已经出现
else{
// 将头指针移动得到重复字符的后一位
while(s[index] != s[i]){
temp[(int)(s[index])] = 0;
index++;
}
index++;
count = i - index + 1;
}
// 更新最大长度值
max = max>count?max:count;
}
return max;
}
运行结果为: