【LeetCode练习】 -- 3. 无重复字符的最长子串

286 阅读1分钟

小知识,大挑战!本文正在参与「程序员必备小知识」创作活动

本文已参与「掘力星计划」,赢取创作大礼包,挑战创作激励金。


题目描述

给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。

示例 1:

输入: s = "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。

示例 2:

输入: s = "bbbbb" 输出: 1 解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。

示例 3:

输入: s = "pwwkew" 输出: 3 解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。   请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。

示例 4:

输入: s = "" 输出: 0

解题方式

方法1:暴力循环

Set结构判断字符是否重复,使用双重循环找出所有的不重复子串

代码

public int lengthOfLongestSubstring2(String s) {

    if (s.equals("")){
        return 0;
    }

    int max = 0;
    // Set的作用是存储不重复的字串
    // 使用Set存储字符串的每个字符,如果能存进去说明该字符没有重复
    Set<Character> set = new HashSet<>();

    int length = s.length();
    // 双重循环,找出每个不重复的子串
    for (int i = 0; i < length; i++) {
        for (int j = i; j < length; j++){
            boolean add = set.add(s.charAt(j));
            // 没有存入set说明该字符已经在set中了
            if (!add){
                max = Math.max(max, set.size());
                set.clear();
                break;
            }
            // 处理最后一个字符未重复的情况
            if (i == length - 1){
                max = Math.max(max, set.size());
            }
        }
    }

    return max;
}

LeetCode运行结果 image.png

方法2: 滑动窗口

窗口包含的子符为不重复子串,计算每个窗口包含的长度并和当前记录的最大长度比较,如果当前子串长度大于记录的最大长度,则将当前子串长度记录成最大长度。

遍历字符串时,当前窗口长度 = 当前位置 - 上一个重复字符的位置 + 1

public static int lengthOfLongestSubstring1(String s) {

    // 数组的位置表示字符,字符的对应位置存入该字符最后一次出现的下标
    int[] last = new int[128];
    Arrays.fill(last, -1);

    int res = 0;
    // 窗口开始位置
    int start = 0;
    // i表示窗口的结束位置
    for (int i = 0; i < s.length(); i++) {

        int ch = s.charAt(i);
        // 窗口开始位置等于字符最后出现的后一位
        // 该字符最后一次出现的位置为新的窗口开始位置
        start = Math.max(start, last[ch] + 1);
        // 如果当前窗口的长度大于已经记录的最大长度,则把当前窗口的长度记录为最大长度
        res   = Math.max(res, i - start + 1);
        // 记录该字符最后一次出现的下标
        last[ch] = i;
    }

    return res;
}

此解法来源于LeetCode

LeetCode运行结果 image.png