Topic
- Hash Table
- Two Pointers
- String
- Sliding Window
Description
https://leetcode.com/problems/longest-substring-without-repeating-characters/
Given a string s, find the length of the longest substring without repeating characters.
Example 1:
Input: s = "abcabcbb"
Output: 3
Explanation: The answer is "abc", with the length of 3.
Example 2:
Input: s = "bbbbb"
Output: 1
Explanation: The answer is "b", with the length of 1.
Example 3:
Input: s = "pwwkew"
Output: 3
Explanation: The answer is "wke", with the length of 3.
Notice that the answer must be a substring, "pwke" is a subsequence and not a substring.
Example 4:
Input: s = ""
Output: 0
Constraints:
- 0 <= s.length <= 5 * 10⁴
- s consists of English letters, digits, symbols and spaces.
Analysis
基本思想:用缓存以字符串的字符为键,下标为值。用左右指针标记最大子字符串起始与末尾下标。移动右指针扫描字符串的字符,与此同时,更新缓存,更新最长值。当发现重复的字符,查找缓存这字符对应下标,左指针指向这下标+1。
方法一:双指针+哈希表
方法二:比方法一精简些
方法三:移动窗口(队列)
方法四:双指针+哈希集
Submission
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Map;
import java.util.Queue;
import java.util.Set;
public class LongestSubstringWithoutRepeatingCharacters {
//方法一:双指针+哈希表
public int lengthOfLongestSubstring1(String s) {
int max = 0, count = 0;
Map<Character, Integer> cache = new HashMap<>();
for (int leftIndex = 0, rightIndex = 0; rightIndex < s.length(); rightIndex++) {
char character = s.charAt(rightIndex);
Integer existIndex = cache.get(character);
if (existIndex != null && existIndex >= leftIndex) {
if (count > max)
max = count;
count = rightIndex - existIndex;
leftIndex = existIndex + 1;
} else {
count++;
}
cache.put(character, rightIndex);
}
return Math.max(max, count);// max()针对字符串完全无重复字符(如:"abc")的情况
}
//方法二:比方法一精简些
public int lengthOfLongestSubstring2(String s) {
int max = 0, leftIndex = 0, rightIndex = 0;
Map<Character, Integer> cache = new HashMap<>();
for (; rightIndex < s.length(); rightIndex++) {
char character = s.charAt(rightIndex);
Integer existIndex = cache.get(character);
if (existIndex != null && existIndex >= leftIndex) {
max = Math.max(max, rightIndex - leftIndex);
leftIndex = existIndex + 1;
}
cache.put(character, rightIndex);
}
return Math.max(max, rightIndex - leftIndex);
}
//方法三:移动窗口(队列)
public int lengthOfLongestSubstring3(String s) {
Queue<Character> queue = new LinkedList<>();
int res = 0;
for (char c : s.toCharArray()) {
while (queue.contains(c)) {
queue.poll();
}
queue.offer(c);
res = Math.max(res, queue.size());
}
return res;
}
//方法四:双指针+哈希集
public int lengthOfLongestSubstring4(String s) {
int maxLen = 0;
Set<Character> window = new HashSet<>();
int left = 0, right = 0;
while (right < s.length()) {
while (window.contains(s.charAt(right)))
window.remove(s.charAt(left++));
window.add(s.charAt(right++));
maxLen = Math.max(maxLen, right - left);
}
return maxLen;
}
}
Test
import static org.junit.Assert.*;
import org.junit.Test;
public class LongestSubstringWithoutRepeatingCharactersTest {
@Test
public void test() {
LongestSubstringWithoutRepeatingCharacters obj = new LongestSubstringWithoutRepeatingCharacters();
assertEquals(3, obj.lengthOfLongestSubstring1("abcabcbb"));
assertEquals(1, obj.lengthOfLongestSubstring1("bbbbb"));
assertEquals(3, obj.lengthOfLongestSubstring1("pwwkew"));
assertEquals(0, obj.lengthOfLongestSubstring1(""));
assertEquals(1, obj.lengthOfLongestSubstring1(" "));
assertEquals(3, obj.lengthOfLongestSubstring1("dvdf"));
assertEquals(2, obj.lengthOfLongestSubstring1("abba"));
assertEquals(3, obj.lengthOfLongestSubstring2("abcabcbb"));
assertEquals(1, obj.lengthOfLongestSubstring2("bbbbb"));
assertEquals(3, obj.lengthOfLongestSubstring2("pwwkew"));
assertEquals(0, obj.lengthOfLongestSubstring2(""));
assertEquals(1, obj.lengthOfLongestSubstring2(" "));
assertEquals(3, obj.lengthOfLongestSubstring2("dvdf"));
assertEquals(2, obj.lengthOfLongestSubstring2("abba"));
assertEquals(3, obj.lengthOfLongestSubstring3("abcabcbb"));
assertEquals(1, obj.lengthOfLongestSubstring3("bbbbb"));
assertEquals(3, obj.lengthOfLongestSubstring3("pwwkew"));
assertEquals(0, obj.lengthOfLongestSubstring3(""));
assertEquals(1, obj.lengthOfLongestSubstring3(" "));
assertEquals(3, obj.lengthOfLongestSubstring3("dvdf"));
assertEquals(2, obj.lengthOfLongestSubstring3("abba"));
assertEquals(3, obj.lengthOfLongestSubstring4("abcabcbb"));
assertEquals(1, obj.lengthOfLongestSubstring4("bbbbb"));
assertEquals(3, obj.lengthOfLongestSubstring4("pwwkew"));
assertEquals(0, obj.lengthOfLongestSubstring4(""));
assertEquals(1, obj.lengthOfLongestSubstring4(" "));
assertEquals(3, obj.lengthOfLongestSubstring4("dvdf"));
assertEquals(2, obj.lengthOfLongestSubstring4("abba"));
}
}