问题:
Given a string, find the length of the longest substring without repeating characters.
Example 1:
Input: “abcabcbb”
Output: 3
Explanation: The answer is “abc”, with the length of 3.
Example 2:
Input: “bbbbb”
Output: 1
Explanation: The answer is “b”, with the length of 1.
Example 3:
Input: “pwwkew”
Output: 3
Explanation: The answer is “wke”, with the length of 3.
Note that the answer must be a substring, “pwke” is a subsequence and not a substring.
答案:
方法1:暴力法 用一个map记录字母的次数
两重循环 第一重循环 首先将map清空: mapping.erase(mapping.begin(), mapping.end());
第二重循环 记录字母的次数 直到字母的次数为2 即检测到一个重复的字母,终止循环,记录长度并更新最大长度
maxAns的值赋值为0,处理空字符串的问题
C++版:
class Solution {
public:
int lengthOfLongestSubstring(string s) {
unordered_map<char, int> mapping;
int maxAns = 0;
int i, j;
for(i = 0; i < s.size(); i++){
mapping.erase(mapping.begin(), mapping.end());
mapping[s[i]]++;
for(j = i + 1; j < s.size(); j++){
mapping[s[j]]++;
if(mapping[s[j]] == 2){
break;
}
}
if((j - i) > maxAns){
maxAns = (j - i);
}
}
return maxAns;
}
};
java:
- 不能用size而用length
- map操作用get和put函数 String 中的charAt函数得到的是字符,不能用s[i]
- map需要判断键是否存在 用containsKey函数
- map可以用clear
class Solution {
public int lengthOfLongestSubstring(String s) {
Map<Character, Integer> mapping = new HashMap<Character, Integer>();
int maxAns = 0;
int i, j;
for(i = 0; i < s.length(); i++){
mapping.clear();
mapping.put(s.charAt(i), 1);
for(j = i + 1; j < s.length(); j++){
if(mapping.containsKey(s.charAt(j))){
mapping.put(s.charAt(j), mapping.get(s.charAt(j)) + 1);
} else {
mapping.put(s.charAt(j), 1);
}
if(mapping.get(s.charAt(j)) == 2){
break;
}
}
if((j - i) > maxAns){
maxAns = (j - i);
}
}
return maxAns;
}
}
Python:
1.字典判断键是否存在用in
2.用len表示长度 并且Python中无++
class Solution(object):
def lengthOfLongestSubstring(self, s):
mapping = {}
maxAns = 0
for i in range(len(s)):
mapping.clear()
mapping[s[i]] = 1
j = i + 1
while j < len(s):
if s[j] in mapping:
mapping[s[j]] = mapping[s[j]] + 1
else:
mapping[s[j]] = 1
if mapping[s[j]] == 2:
break;
j = j + 1
if (j - i) > maxAns:
maxAns = (j - i)
return maxAns
方法2:滑动窗口法:
map记录字符最后出现的位置
维护一个滑动窗口 left是其左边界,右边界是当前访问的字符,初始化为-1
如果当前访问的字符已经出现过,如果在滑动窗口中,就需要删除该字符,即将left赋值为出现的字符的位置
如果不在滑动窗口则没事继续加进来
注意点:
- 更新最大长度必须在左边界更新后进行
- 除了判断字符是否出现过还要判断是否在当前滑动窗口
例子:
“abbb”
初始化: left为-1,
i=0,a未出现过,不更新left,记录位置a-> 0,窗口长度1
i=1,b未出现过,不更新left,记录位置b->1,窗口长度2
i=2,b出现过,位置为1,且出现过的b在窗口中,需要删除,即将left赋值为b最后的位置1,重新开始窗口,记录新的b位置为2,窗口长度为1
i=3,a出现过,位置为0,但不知当前窗口中,继续加入窗口,新的a位置为3,窗口长度为2
结束,最大长度为2
C++:
class Solution {
public:
int lengthOfLongestSubstring(string s) {
//记录每个字符最后出现的位置
unordered_map<char, int> mapping;
//滑动窗口左边位置 它总在滑动窗口最左边字符的前一位,以便计算窗口长度,初始化为-1
int left = -1;
int maxAns = 0;
for(int i = 0; i < s.size(); i++){
//判断当前字符是否出现过 即mapping.count(s[i])是否为0,是0表示未出现,1表示出现过
//如果该字符出现过且在滑动窗口中mapping[s[i]] > left
//删除该字符,即将left赋值为出现的字符的位置
if(mapping.count(s[i]) && mapping[s[i]] > left){
left = mapping[s[i]];
}
mapping[s[i]] = i;//储存字符的位置无论是否出现过
//更新最大长度
maxAns = max(maxAns, i - left);
}
return maxAns;
}
};
java:
max函数在Math类中
class Solution {
public int lengthOfLongestSubstring(String s) {
Map<Character, Integer> mapping = new HashMap<Character, Integer>();
//滑动窗口左边位置 它总在滑动窗口最左边字符的前一位,以便计算窗口长度,初始化为-1
int left = -1;
int maxAns = 0;
for(int i = 0; i < s.length(); i++){
if(mapping.containsKey(s.charAt(i)) && mapping.get(s.charAt(i)) > left){
left = mapping.get(s.charAt(i));
}
mapping.put(s.charAt(i), i);//储存字符的位置无论是否出现过
//更新最大长度
maxAns = Math.max(maxAns, i - left);
}
return maxAns;
}
}
Python:
class Solution(object):
def lengthOfLongestSubstring(self, s):
mapping = {}
left = -1
maxAns = 0
for i in range(len(s)):
if s[i] in mapping and mapping[s[i]] > left:
left = mapping[s[i]]
mapping[s[i]] = i
maxAns = max(maxAns, i - left)
return maxAns
解法3:
上个版本的精简版本
不用map存储位置而改用向量存储,总共存储256个字符,有ASCII码的字符总共有256个,全部初始化为-1
改动的位置:不用判断字符是否出现过,没出现过,位置初始化为-1,而left最小值为-1,故不可能大于left,因此不能进入条件语句中,所以不用判断
C++:
class Solution {
public:
int lengthOfLongestSubstring(string s) {
vector<int> mapping(256, -1);
//滑动窗口左边位置 它总在滑动窗口最左边字符的前一位,以便计算窗口长度,初始化为-1
int left = -1;
int maxAns = 0;
for(int i = 0; i < s.size(); i++){
//如果该字符出现过且在滑动窗口中mapping[s[i]] > left
//删除该字符,即将left赋值为出现的字符的位置
if(mapping[s[i]] > left){
left = mapping[s[i]];
}
mapping[s[i]] = i;//储存字符的位置无论是否出现过
//更新最大长度
maxAns = max(maxAns, i - left);
}
return maxAns;
}
};
java:
Arrays.fill函数给数组赋一样的值
class Solution {
public int lengthOfLongestSubstring(String s) {
int[] mapping = new int[256];
Arrays.fill(mapping, -1);
//滑动窗口左边位置 它总在滑动窗口最左边字符的前一位,以便计算窗口长度,初始化为-1
int left = -1;
int maxAns = 0;
for(int i = 0; i < s.length(); i++){
if(mapping[s.charAt(i)] > left){
left = mapping[s.charAt(i)];
}
mapping[s.charAt(i)] = i;//储存字符的位置无论是否出现过
//更新最大长度
maxAns = Math.max(maxAns, i - left);
}
return maxAns;
}
}
Python:
Python ord() 函数将ASCII码转为整数 chr()函数将整数转为ASCII码
class Solution(object):
def lengthOfLongestSubstring(self, s):
mapping = [-1] * 256
left = -1
maxAns = 0
for i in range(len(s)):
if mapping[(ord)s[i]] > left:
left = mapping[(ord)s[i]]
mapping[(ord)s[i]] = i
maxAns = max(maxAns, i - left)
return maxAns
方法4:
利用set去重的特点
把出现过的字符都放入set中,遇到set中没有的字符就加入set中并更新结果,如果遇到重复的,则从左边开始删字符,直到删到重复的字符停止,
例如“abba”
初始i为0,left也为0
i=0,set中没有a,加入a,更新最大长度,i向后移动
i=1,set中没有b,加入b,更新最大长度,i向后移动
i=2,set中有b,开始删从left删字符,先删a,left为1,set还剩b,此时依然重复,继续删b,left =2,set没有重复的元素,然后将s[2]=b,加入进来,更新最大长度,i向后移动
i=3,set中没有a,加入a,更新最大长度,i向后移动
C++:
unordered_set以散列替代了红黑树,速度更快,但是没有了排序功能
set中erase函数既可以传删除元素的迭代器也可以传要删除的值
(int)mapping.size()要做类型转换
class Solution {
public:
int lengthOfLongestSubstring(string s) {
unordered_set<char> mapping;
int left = 0;
int maxAns = 0;
int i = 0;
while(i < s.size()){
if(!mapping.count(s[i])){
mapping.insert(s[i++]);
maxAns = max(maxAns, (int)mapping.size());
} else {
mapping.erase(s[left++]);
}
}
return maxAns;
}
};
java:
java中set string 首字母都是大写Set String
Set中查看是否存在用contains函数
加入元素用add函数 删除用remove函数
String中是length函数 Set是size函数
class Solution {
public int lengthOfLongestSubstring(String s) {
Set<Character> mapping = new HashSet<Character>();
int left = 0;
int maxAns = 0;
int i = 0;
while(i < s.length()){
if(!mapping.contains(s.charAt(i))){
mapping.add(s.charAt(i++));
maxAns = Math.max(maxAns, mapping.size());
} else {
mapping.remove(s.charAt(left++));
}
}
return maxAns;
}
}
Python:
可以使用大括号 { } 或者 set() 函数创建集合,注意:创建一个空集合必须用 set() 而不是 { },因为 { } 是用来创建一个空字典。
class Solution(object):
def lengthOfLongestSubstring(self, s):
mapping = set()
left = 0
maxAns = 0
i = 0
while i < len(s):
if s[i] not in mapping:
mapping.add(s[i])
i = i + 1
maxAns = max(maxAns, len(mapping))
else:
mapping.remove(s[left])
left = left + 1
return maxAns