返回
抓耳挠腮的无重复字符最长子串
前端
2023-11-27 09:01:02
**挑战:**
你有多少次在写代码时遇到过这样的问题:给定一个字符串,你需要找到其中不包含重复字符的最长子串?
**leetcode 中的经典:**
在 leetcode 中,这个问题被称为 "无重复字符的最长子串"。它是一个经典的问题,也是面试中最常见的问题之一。
**解法的多维度:**
解决这个问题的方法有很多。你能想到多少种呢?
**三种最常用的方法:**
其中,三种最常用的方法分别是:
1. 动态规划
2. 滑动窗口
3. 哈希表
**思维导图:**
为了帮助你更好地理解这些方法,我们准备了一份思维导图。
**全部解法:**
现在,让我们来看看每种方法的具体实现。
**方案 1:**
动态规划
**思路:**
我们可以使用动态规划来解决这个问题。具体来说,我们可以定义一个 dp 数组,其中 dp[i] 表示字符串 s[0...i] 中不包含重复字符的最长子串的长度。
**代码:**
```java
public int lengthOfLongestSubstring(String s) {
if (s == null || s.length() == 0) {
return 0;
}
int[] dp = new int[s.length()];
dp[0] = 1;
int maxLen = 1;
for (int i = 1; i < s.length(); i++) {
int lastIndex = -1;
for (int j = 0; j < i; j++) {
if (s.charAt(j) == s.charAt(i)) {
lastIndex = j;
break;
}
}
if (lastIndex == -1) {
dp[i] = dp[i - 1] + 1;
} else {
dp[i] = Math.max(dp[i - 1], dp[lastIndex] + 1);
}
maxLen = Math.max(maxLen, dp[i]);
}
return maxLen;
}
方案 2:
滑动窗口
思路:
我们可以使用滑动窗口来解决这个问题。具体来说,我们可以使用两个指针来标记滑动窗口的左右边界。当我们遇到重复字符时,我们可以将左指针移动到重复字符的下一个位置。
代码:
public int lengthOfLongestSubstring(String s) {
if (s == null || s.length() == 0) {
return 0;
}
int left = 0;
int right = 0;
int maxLen = 0;
Set<Character> set = new HashSet<>();
while (right < s.length()) {
if (!set.contains(s.charAt(right))) {
set.add(s.charAt(right));
maxLen = Math.max(maxLen, right - left + 1);
right++;
} else {
set.remove(s.charAt(left));
left++;
}
}
return maxLen;
}
方案 3:
哈希表
思路:
我们可以使用哈希表来解决这个问题。具体来说,我们可以使用一个哈希表来存储字符串中每个字符最后出现的位置。当我们遇到重复字符时,我们可以将左指针移动到重复字符最后出现的位置的下一个位置。
代码:
public int lengthOfLongestSubstring(String s) {
if (s == null || s.length() == 0) {
return 0;
}
int left = 0;
int right = 0;
int maxLen = 0;
Map<Character, Integer> map = new HashMap<>();
while (right < s.length()) {
if (map.containsKey(s.charAt(right))) {
left = Math.max(left, map.get(s.charAt(right)) + 1);
}
map.put(s.charAt(right), right);
maxLen = Math.max(maxLen, right - left + 1);
right++;
}
return maxLen;
}
总结:
无重复字符的最长子串是一个经典的问题。我们可以使用动态规划、滑动窗口和哈希表等方法来解决这个问题。每种方法都有其