大厂面试手撕面试题:求一个字符串中最长不重复子串的长度(亲测可用的java实现)

这是一个常见的面试题,要求找到字符串中最长的不重复子串的长度。我们可以使用 滑动窗口哈希集合 的方法来有效地解决这个问题。

思路:

  1. 滑动窗口:我们通过维护一个窗口来追踪当前不重复的子串。窗口的左边和右边分别由两个指针表示,我们通过右指针来扩展窗口,左指针则会根据需要收缩窗口。
  2. 哈希集合:为了高效检查一个字符是否已经在当前窗口中,我们可以使用哈希集合来存储窗口中的字符。
  3. 当我们遇到重复字符时,左指针会移动到重复字符之后的位置,确保窗口内的字符不重复。

具体步骤:

  • 初始化一个空的哈希集合,用于存储当前窗口内的字符。
  • 使用两个指针:left 和 rightright 用于扩展窗口,left 用于收缩窗口。
  • 如果当前字符(s[right])不在哈希集合中,表示没有重复字符,将其加入集合,并更新最大长度。
  • 如果当前字符已经在集合中,移动 left 指针,直到窗口中的字符没有重复。
  • 每次移动 right 指针时,更新当前窗口的最大长度。

时间复杂度:

  • 时间复杂度是 O(n),其中 n 是字符串的长度。因为每个字符最多只会被访问两次(一次通过右指针,另一次通过左指针)。

空间复杂度:

  • 空间复杂度是 O(min(n, m)),其中 n 是字符串的长度,m 是字符集的大小(对于英语字符集而言,m 通常是常数 256)。

Java 代码实现:

import java.util.HashSet;

public class LongestUniqueSubstring {
    public static int lengthOfLongestSubstring(String s) {
        // 用一个哈希集合来记录当前窗口内的字符
        HashSet<Character> set = new HashSet<>();
        
        int left = 0;  // 滑动窗口的左指针
        int maxLength = 0;  // 记录最长子串的长度
        
        // 遍历字符串
        for (int right = 0; right < s.length(); right++) {
            // 当右指针指向的字符已经在集合中,收缩窗口
            while (set.contains(s.charAt(right))) {
                set.remove(s.charAt(left));
                left++;
            }
            // 将当前字符加入集合
            set.add(s.charAt(right));
            // 更新最大长度
            maxLength = Math.max(maxLength, right - left + 1);
        }
        
        return maxLength;
    }

    public static void main(String[] args) {
        String s = "abcabcbb";
        System.out.println("The length of the longest substring without repeating characters is: " 
                            + lengthOfLongestSubstring(s));  // Output: 3 ("abc")
    }
}

代码解释:

  1. set 是一个哈希集合,用来存储当前窗口中的字符。
  2. left 是滑动窗口的左指针,right 是滑动窗口的右指针。
  3. 遍历字符串时,检查当前字符 s.charAt(right) 是否已经在窗口中。如果在,就不断移动 left 指针,直到窗口内没有重复字符。
  4. 每次更新 right 指针时,计算当前窗口的长度,更新最大长度 maxLength

示例:

对于输入 "abcabcbb"

  • 经过滑动窗口的计算,最长的不重复子串为 "abc",长度为 3。

关注公众号“大模型全栈程序员”回复“小程序”获取1000个小程序打包源码。更多免费资源在http://www.gitweixin.com/?p=2627

发表评论

邮箱地址不会被公开。 必填项已用*标注