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.
最长不重复子串:
自己的实现代码
public static int maxArr(int[] arr) {
int max = arr[0];
for(int i=1;i<arr.length;i++) {
if(arr[i] >= max) { // 拿每个值与max相比
max = arr[i];
}
}
return max;
}
public static int lengthOfLongestSubstring(String s) {
if(s == null || s.length() == 0) // 这里两个条件判断都不能少;
return 0;
char[] chs = s.toCharArray();
int[] arr = new int[chs.length]; // arr[i]中存放以chs[i]结尾的最长不重复子串的长度
arr[0] = 1;
for(int i=1;i<chs.length;i++) {
arr[i] = arr[i-1] + 1;
for(int j=i-arr[i-1];j<i;j++) {
if(chs[i] == chs[j]) {
arr[i] = i - j;
}
}
}
return maxArr(arr);
}
1)如果没有s.length()==0这个判断,空字符串“”,就会造成arr[0] = 1,这一行代码出现数组越界异常
别人的代码1
核心思想:使用散列集跟踪最长的子字符串,而不重复字符,使用快速指针j查看字符j是否在散列集中,
如果不是,很好,将其添加到散列集中,向前移动j并更新最大长度;
否则,使用慢速指针i从头部删除,直到我们可以将字符j放入散列集中。
(直到可以将字符j插入hashset时,说明子串中从与字符j相同的字符之前的所有的字符都被删完了)
public int lengthOfLongestSubstring(String s) {
int i = 0, j = 0, max = 0;
Set<Character> set = new HashSet<>();
while (j < s.length()) {
if (!set.contains(s.charAt(j))) {
set.add(s.charAt(j++));
max = Math.max(max, set.size());
} else {
set.remove(s.charAt(i++));
}
}
return max;
}
别人代码1改进:
if we use hashmap
to store the position of occured characters. Then we don't need to find the next start position by set.remove(s.charAt(i++));
We just put i = map[s[j]] + 1
别人的代码2:
使用的队列,核心思路和上面使用的hashset解决问题是一样的
缺点,遍历队列查找,比hash查找更加耗时
public int lengthOfLongestSubstring(String s) {
Queue<Character> queue = new LinkedList<>();
int res = 0;
for (char c : s.toCharArray()) {
while (queue.contains(c)) { // 一旦发现重复元素则把包含重复元素之前所有元素poll掉
queue.poll();
}
queue.offer(c);
res = Math.max(res, queue.size());
}
return res;
}