您的位置:首页 > 其它

LEETCODE学习 -- 3.无重复字符的最长子串

2020-04-26 19:02 429 查看

LEETCODE-3.无重复字符的最长子串

题目-无重复字符的最长子串

给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。

示例1:
输入: “abcabcbb”
输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。

示例2:
输入: “bbbbb”
输出: 1
解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。

示例3:
输入: “pwwkew”
输出: 3
解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。
请注意,你的答案必须是 子串 的长度,“pwke” 是一个子序列,不是子串。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/longest-substring-without-repeating-characters

方法一 滑动窗口+hash表

直接两层循环遍历复杂度为O(n^2),故不采用,而使用一个哈希表。哈希表signal每个元素的标号表示该元素与空格符的差值,每个元素的值表示出现在字符串内的位置。例如,在字符串abbacb中,字符‘c’出现在第4位(从0开始计算),其哈希值为c-‘ ’ = 99 - 32 = 67,那么设置signal[67] = 4。在这里表的大小只是个人习惯问题,也可以从ascii码为0的空字符开始。

首先初始化signal,将其每一个元素初始化为-1。随后对输入字符串s从头开始遍历,如果当前字符c的哈希值在signal表中的值为-1,那么将其更改为c在字符串中的位置。如果在signal中的值大于等于0,说明该元素在当前子串中出现过。统计当前子串的长度,如果超过之前的最大值,就将最大值更新。将遍历位置修改为c在signal表中元素值的位置重新开始新一个子串的查找,清空signal表,重复之前的过程。

int lengthOfLongestSubstring(char * s){
int signal[96] = {-1};
int longest_sub_length = 0;
int cur_sub_length = 0;
int cur_sub_position = 0;
int i = 0;
int j = 0;
memset(signal,-1,sizeof(signal));
while(s[i] != '\0')
{
if(signal[s[i]-' '] == -1)  //当前字符未重复过
{
signal[s[i]-' '] = i;
i++;
cur_sub_length++;
continue;
}
else   //当前字符是重复字符
{
longest_sub_length = cur_sub_length > longest_sub_length ? cur_sub_length : longest_sub_length;
cur_sub_position = signal[s[i]-' '] ;
cur_sub_length = 0;
for(j = 0; j < 95; j++)
signal[j] = -1;
i = cur_sub_position + 1;
}
}
longest_sub_length = cur_sub_length > longest_sub_length ? cur_sub_length : longest_sub_length;

return longest_sub_length;

}

方法二 优化滑动窗口

方法一有一个多余的部分,即当出现重复字符,需要重置哈希表,之前已经在表中存在的元素将被初始化,还需要对这些元素进行重复的录入。所以优化如下:

  1. start指针表示当前子串的开始位置,哈希表构建还是和原来一样,不过元素存储的值从1开始计算。
  2. i表示当前遍历到的元素位置
  3. 如果s[i] > start,说明当前遍历到的元素在目前的子串的前缀中出现过,所以该子串遍历结束,计算子串长度
  4. 最重要的修改:当出现重复字符时,当前遍历的位置不会前跳,而是继续向后遍历,相对的只要修改子串的起始位置即可。
    例如:字符串‘ilovelty’,起初子串的开始位置为0,当遍历到第二个’l‘时满足重复条件,此时更新最大字串长度,然后将子串的开始位置设置为o,即开始位置为2。遍历结束后最长子串为’ovelty’,长度为6。
int lengthOfLongestSubstring(char * s){
int i, j = 0, length = 0, max_length = 0, signal[128] = {0}, start = 0;
for(i=0;s[i]!='\0';i++)
{
if(signal[s[i]]>start)
{
length = i-start;
if(length>max_length)
{
max_length = length;
}
start = signal[s[i]];
}
signal[s[i]] = i+1;
}
length = i-start;
return length>max_length?length:max_length;
}

参考

https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/solution/cyu-yan-shuang-yi-bai-by-wu-sheng-23/

  • 点赞 1
  • 收藏
  • 分享
  • 文章举报
Therock_of_lty 发布了7 篇原创文章 · 获赞 8 · 访问量 405 私信 关注
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: