文章作者:Tyan
博客:noahsnail.com | CSDN | 简书
1. 问题描述
Given a string, find the length of the longest substring without repeating characters.
Examples:
Given "abcabcbb", the answer is "abc", which the length is 3.
Given "bbbbb", the answer is "b", with the length of 1.
Given "pwwkew", 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.
2. 求解
方法一
当遍历第i个字符时,需要判断[index,i-1]
的字符中是否有与s[i]重复的字符,如果字符s[j]与s[i]重复,index直接变为j + 1,重新计算不重复字符的数量,如果[index,i-1]
的字符中没有与s[i]重复的字符,则不重复字符计数count++
。
public class Solution {
public int lengthOfLongestSubstring(String s) {
int max = 0;
int count = 0;
int index = 0;
//[index,i-1]中是否有与s[i]重复的字符
boolean flag = false;
for(int i = 0; i < s.length(); i++) {
flag = false;
char ch = s.charAt(i);
//如果s[j]与s[i]重复,index直接变为j + 1,重新计算不重复字符数
for(int j = index; j < i; j++) {
if(s.charAt(j) == s.charAt(i)) {
flag = true;
index = j + 1;
count = i - j;
break;
}
}
if(!flag) {
count++;
if(count > max) {
max = count;
}
}
}
return max;
}
}
方法二
方法二的思路是看到有重复问题,首先想到哈希表,由于求解的是不重复子串,因此需要将子串分为两部分,一部分为(i,n-1),一部分为(j,i),如果s[i]不在(j,i)中,则将s[i]放入哈希表中,同时计数器加1,如果s[i]在(j,i)中,则找到(j,i)中与s[i]重复的字符ch,将其移除,当然ch之前的字符也要将其从哈希表中移除,因为包含ch的子串一定与s[i]重复,每移除一个字符,j++。重复上述过程,直至i到字符串最后。每一个找的子串是从(j,i)不重复的最长子串。这里的j是方法一中的index。思路与方法一是一致的,区别是使用哈希表来判断重复而不是使用循环。
public class Solution {
public int lengthOfLongestSubstring(String s) {
Map<Character, Character> map = new HashMap<Character, Character>();
int max = 0;
int count = 0;
int j = 0;
for(int i = 0; i < s.length(); i++) {
char ch = s.charAt(i);
//如果有重复字符,逐个移除字符,直到移除了与第i个字符重复的字符
if(map.containsKey(ch)) {
while(map.containsKey(ch)) {
map.remove(s.charAt(j));
j++;
count--;
}
count++;
map.put(ch, ch);
}else {
map.put(ch, ch);
count++;
if(count > max) {
max = count;
}
}
}
return max;
}
}
备注:Leetcode测试时,发现方法一比方法二速度更快。