3. 无重复字符的最长子串
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: “abcabcbb”
输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。
示例 2:
输入: “bbbbb”
输出: 1
解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。
示例 3:
输入: “pwwkew”
输出: 3
解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。
请注意,你的答案必须是 子串 的长度,“pwke” 是一个子序列,不是子串。
头脑风暴:一般情况下遍历最长无重复子串是逐个字符遍历“a”ok、“ab”ok、“abc”ok、“abca”warning!重复了,“b”ok、“bc”ok、“bca”ok、“bcab”warning!重复了…
发现规律:
- 逐个遍历
- 一旦发现重复,遍历回退到已存在的重复字符的后一个位置
思路:hash表+滑动窗口
- slidingWindowQeueu将s字符值作为index,每遍历的的字符在hash中标记:该字符的位置+1
- 若head遍历到的字符存在在hash中存在要分两种情况讨论:
- 该字符已存在在窗口内,需要调整窗口,将窗口左侧移动到hash中的位置。
- 该字符已存在在窗口外,不需要调整窗口。
- 更新滑动窗口大小
- 检查此时窗口大小是否最大,若为最大窗口值,更新max的值
int lengthOfLongestSubstring(char * s){
int max = 0;//字符串的最长长度
int ret = 0;//用于滑动窗口大小
int head = 0;//窗口右侧指针
int rear = 0;//窗口左侧指针
int slidingWindowQeueu[128] = {0};
if(strlen(s) == 0)
return 0;
while(head <= strlen(s) - 1)
{
if(slidingWindowQeueu[s[head]] )//窗口右指针指向的字符已存在
{
rear = slidingWindowQeueu[s[head]] > rear ? slidingWindowQeueu[s[head]] : rear ;
//若此字符已存在在窗口外,不作处理。若此字符已存在在窗口内,则滑动窗口,使窗口左侧位置设置为hash中的值。
}
ret = head - rear + 1;//记录此次遍历时的窗口大小
max = ret > max ? ret : max;//记录最大的窗口大小
slidingWindowQeueu[s[head]] = head +1;//记录此字符出现的位置的前一个位置
head++;//前移
}
return max;
}
转载大神:
执行用时 :4 ms, 在所有 C 提交中击败了95.17%的用户
内存消耗 :7.1 MB, 在所有 C 提交中击败了80.73%的用户
时间复杂度O(n),空间复杂度O(n)
int lengthOfLongestSubstring(char * s){
int prior = 0; //上次状态下最长子串的长度
int left = 0;
int dict[256] = {0}; //映射ASCII码
int right = 1; //表示字符串中第right个字符
int i;
while(*s != '\0'){
i = *s-0; //字符转换为整数
if(dict[i] > left)
left = dict[i];
dict[i] = right;
prior = (prior>right-left)?prior:right-left; //right的值比对应的数组下标大1
s++;
right++;
}
return prior;
}
作者:jack-153
链接:https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/solution/3wu-zhong-fu-zi-fu-de-zui-chang-zi-chuan-by-jack-1/
来源:力扣(LeetCode)