返回

无重复字符的最长子字符串——Java实现

后端

引言

在计算机科学中,“无重复字符的最长子字符串”问题是一个经典的面试题。给定一个字符串,我们需要找到其中不包含重复字符的最长子字符串。例如,对于字符串“abcabcbb”,最长子字符串是“abc”,因为它不包含任何重复字符,长度为3。

解决方案一:滑动窗口

滑动窗口算法是一种常用的字符串处理算法,可以用来高效地解决无重复字符的最长子字符串问题。该算法的基本思想是使用一个窗口在字符串中滑动,并记录窗口中出现的字符。当窗口中出现重复字符时,窗口向右移动一位,继续扫描剩余的字符串。同时,我们不断更新无重复字符的最长子字符串的长度。

public class Solution {
    public int lengthOfLongestSubstring(String s) {
        int n = s.length();
        Set<Character> set = new HashSet<>();
        int maxLen = 0;
        int left = 0;
        for (int right = 0; right < n; right++) {
            char c = s.charAt(right);
            while (set.contains(c)) {
                set.remove(s.charAt(left));
                left++;
            }
            set.add(c);
            maxLen = Math.max(maxLen, right - left + 1);
        }
        return maxLen;
    }
}

在上面的Java代码中,我们使用了一个HashSet来存储窗口中出现的字符。当窗口中出现重复字符时,我们将窗口向右移动一位,并不断更新无重复字符的最长子字符串的长度。这个算法的时间复杂度为O(n),空间复杂度为O(n),其中n是字符串的长度。

解决方案二:改进的滑动窗口

我们可以对滑动窗口算法进行改进,使用一个数组来存储窗口中出现的字符的最后出现位置。这样,当窗口中出现重复字符时,我们可以直接跳到重复字符的最后出现位置,而不用从头开始扫描整个窗口。

public class Solution {
    public int lengthOfLongestSubstring(String s) {
        int n = s.length();
        int[] lastIndex = new int[128];
        int maxLen = 0;
        int left = 0;
        for (int right = 0; right < n; right++) {
            char c = s.charAt(right);
            if (lastIndex[c] > 0) {
                left = Math.max(left, lastIndex[c]);
            }
            lastIndex[c] = right + 1;
            maxLen = Math.max(maxLen, right - left + 1);
        }
        return maxLen;
    }
}

在上面的Java代码中,我们使用了一个数组lastIndex来存储窗口中出现的字符的最后出现位置。当窗口中出现重复字符时,我们将窗口向右移动到重复字符的最后出现位置,并不断更新无重复字符的最长子字符串的长度。这个算法的时间复杂度为O(n),空间复杂度为O(n),其中n是字符串的长度。

结语

在本文中,我们介绍了两种解决无重复字符的最长子字符串问题的Java实现。滑动窗口算法是一种常用的字符串处理算法,可以用来高效地解决这个问题。我们可以对滑动窗口算法进行改进,使用一个数组来存储窗口中出现的字符的最后出现位置,从而进一步提高算法的效率。这些算法的时间复杂度都是O(n),空间复杂度都是O(n),其中n是字符串的长度。