【题目概要】
3. 无重复字符的最长子串
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例 2:
输入: "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
【思路分析】
- 无重复字符最长子串參考文献
【示例】字符串是:“fabcade”。
1、当开始比较字符串的时候,begin指向了第一个字符f,now也指向了第一个字符f,当前只有一个字符,也就不需要比较是否重复。
2、然后读取第二个字符,begin依然指向f,now指向了字符a,这个就需要比较一下a是否与之前的相同,没有相同的就继续读取。
3、当now指向第二个a的时候,begin指向f,此时发现前面已经有了一个a了,(这里可以先记录一下当前字符串长度)所以begin就需要往后移动到a后面的b的位置,则当前的字符串为:bca,之后继续读取d,等等等。
总而言之,滑动窗口记录了当前无重复的字符串,当遇到重复的时候,就把begin指针往后移动到不重复的位置(也就是前面那个重复字符的后面),然后继续遍历字符串到最后
【代码示例】
int lengthOfLongestSubstring(char* s)
{
int maxlen = 0,currlen = 0;
int table[128], i, j, start = 0;
memset(table, 0, sizeof(table));
for (i = 0; s[i] != '\0'; ++i){
int num = ++table[s[i]];
判斷是否有重複,一個字符出現兩次,則期間有重複
if( num == 2 )
{
//判断放在进入的第一步,后面会将currlen变化
if (currlen > maxlen){
maxlen = currlen;
}
for(j = start; j < i; ++j){
在重複的期間找到是哪一個字符於最後的重複,下次的start位置就要移動到該值索引的下一個
if (s[j] == s[i]){
table[s[j]] = 1;
start = j+1;
//后续的循环不需要执行
break;
}
else{
減少currlen的值,一直減到重複值後面的數(不爲0)開始下一次計數、相應的標誌位清空,
--currlen;
//不属于下一次计算的范围内,因此需要把之前的记录清空
table[s[j]] = 0;
}
}
}
else{
++currlen;
}
}
//特殊情况是currlen是字符串的全长,则表示没有进入判断maxlen
if (currlen > maxlen){
maxlen = currlen;
}
return maxlen;
}
【代码示例2】
【耗时较长,不建议使用】
bool check(char *a, int num, int len)
{
for(int i=0; i<len; i++)
{
if(a[i] == num)
return false;
}
return true;
}
// 回溯算法的思路
int lengthOfLongestSubstring(char * s)
{
int len = strlen(s);
if(len == 0)
return 0;
char *re = (char*)malloc(sizeof(char)*len);
int tmax = 1;
int max = 1;
for(int h=0; h<len; h++)
{
int k = 0;
re[k] = s[h];
for(int i=h+1; i<len; i++)
{
if(check(re, s[i], k+1))
{
re[++k] = s[i];
tmax++;
}
else
break;
}
//不管是否有相等的,都需要比较一次,其tmax必须要在下一次循环前置为1
if(tmax > max)
{
max = tmax;
}
tmax = 1;
//memset(re, 0, len);
}
return max;
}