返回

抓耳挠腮的无重复字符最长子串

前端





**挑战:** 

你有多少次在写代码时遇到过这样的问题:给定一个字符串,你需要找到其中不包含重复字符的最长子串?

**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;
}

总结:

无重复字符的最长子串是一个经典的问题。我们可以使用动态规划、滑动窗口和哈希表等方法来解决这个问题。每种方法都有其