文章作者: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直接變?yōu)閖 + 1,重新計算不重復字符的數(shù)量,如果[index,i-1]
的字符中沒有與s[i]重復的字符,則不重復字符計數(shù)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直接變?yōu)閖 + 1,重新計算不重復字符數(shù)
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]放入哈希表中,同時計數(shù)器加1,如果s[i]在(j,i)中,則找到(j,i)中與s[i]重復的字符ch,將其移除,當然ch之前的字符也要將其從哈希表中移除,因為包含ch的子串一定與s[i]重復,每移除一個字符,j++。重復上述過程,直至i到字符串最后。每一個找的子串是從(j,i)不重復的最長子串。這里的j是方法一中的index。思路與方法一是一致的,區(qū)別是使用哈希表來判斷重復而不是使用循環(huán)。
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測試時,發(fā)現(xiàn)方法一比方法二速度更快。