3.无重复字符的最长子串
食用指南:
Leetcode专栏开启了,由于博主闭关期末,所以每日只能一题
尽量做到一题多解,先说思路,之后代码实现,会添加必要注释
语法或STL内容会在注意点中点出,新手友好
欢迎关注博主神机百炼专栏,内涵算法基础详细讲解和代码模板
题目描述:
-
给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。
s 由英文字母、数字、符号和空格组成
-
代码背景
class Solution {
public:
int lengthOfLongestSubstring(string s) {
}
};
- 题目来源:https://leetcode.cn/problems/longest-substring-without-repeating-characters/submissions/
题目分析:
-
经典滑动窗口
-
法一:自己实现字符串内字符数目记录数组
由于所有出现的字符都在ASCII码表当中,
所以开一个Hash[128]就可以记录ASCII表中所有可见字符出现次数
-
法二:STL的unordered_map实现字符记录
unordered_map具有泛型<类型1,类型2>
利用字符char为键,出现次数为值
unmap[s[i]]就是字符s[i]的出现次数
需要注意区分unmap.find()和此处出现次数unmap[s[i]]的区别
算法模板:
代码实现:
- 滑动窗口本身最差时间复杂度就是i j两指针都走了一遍s
- 最差时间复杂度O(2n)
法一:unordered_map<>
class Solution {
public:
int lengthOfLongestSubstring(string s) {
int len = 0;
unordered_map<char, int> Hash;
for(int i=0, j=0; j<s.size(); j++){
Hash[s[j]]++;
while(Hash[s[j]] > 1) Hash[s[i]]--, i++;
len = max(len, j-i+1);
}
return len;
}
};
法二:Hash[128]
- ASCII码表中可见字符都在前128个
class Solution {
public:
int lengthOfLongestSubstring(string s) {
int len = 0;
int Hash[128];
memset(Hash, 0, sizeof(Hash));
for(int i=0, j=0; j<s.size(); j++){
Hash[s[j]-' ']++;
while(Hash[s[j]-' '] > 1) Hash[s[i]-' ']--, i++;
len = max(len, j-i+1);
}
return len;
}
};
注意点:
1. ASCII码表常识:
-
ASCII码表中共有256个字符
但是可见的字符都在前128个
可见字符以空格space’ '的ASCII码值最小,为32
-
空字符串长度为1,因为\0结尾
2. unmap.count() 和 unmap[s[i]]的区别:
- unmap[s[i]]的s[i]是key,是哈希表索引
unmap[s[i]]本身是value,是哈希表内值 - unmap.count(key)是说哈希表中这个key有没有对应的value
有则返回1,没有返回0 - 所以说s = “aa”;
unmap[s[0]] == unmap[s[1]] == 2;
但
unmap.count(s[0]) == unmap.count(s[1]) == 1;