leetcode热题解析-无重复字符的最长子串

Problem: 3. 无重复字符的最长子串

题目

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


示例 1:

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

示例 2:

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

示例 3:

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

提示:

  • 0 <= s.length <= 5 * 10^4
  • s 由英文字母、数字、符号和空格组成

思考过程

在这道题目中,我们要找到字符串中不含重复字符的最长子串的长度。最直接的方法是枚举所有可能的子串,然后检查它们是否有重复字符,但这显然会非常低效。为了解决这个问题,我们需要想出一种更高效的方法。

解题思路

我们可以使用滑动窗口(Sliding Window)的方法来解决这个问题。滑动窗口是一种非常实用的算法技巧,尤其是在数组或字符串的子序列、子数组问题中。具体来说,我们会维护一个动态窗口,并且用一个 Set 来记录窗口中所有字符的集合。

  1. 定义窗口边界:我们使用两个指针 ij 来定义窗口的左右边界。i 代表当前字符的位置,j 是窗口的左边界。
  2. 窗口移动:我们遍历字符串,每次将 i 指向的字符添加到 Set 中。如果添加成功(即当前字符未出现在窗口中),继续遍历。如果添加失败(即当前字符已在窗口中),我们将 res 更新为当前窗口的最大长度,并开始移动 j 来缩小窗口直到可以重新添加当前字符为止。
  3. 更新结果:我们在每次窗口成功移动后,更新结果的最大值。

图解

image.png

Code

class Solution {
    public int lengthOfLongestSubstring(String s) {
        int n = s.length();
        Set<Character> set = new HashSet<>();
        int res = 0;
        char[] str = s.toCharArray();
        for(int i = 0, j = 0; i < n; i++){
            if(set.add(str[i])){
                continue;
            }
            res = Math.max(res, set.size());
            while(j < n && str[j] != str[i]){
                set.remove(str[j++]);
            }
            j++;
        }
        res = Math.max(res, set.size());
        return res;
    }
}
func lengthOfLongestSubstring(s string) int {
	n := len(s)
	set := make(map[byte]struct{})
	res := 0
	j := 0

	for i := 0; i < n; i++ {
		if _, found := set[s[i]]; !found {
			set[s[i]] = struct{}{}
			continue
		}
		if len(set) > res {
			res = len(set)
		}
		for j < n && s[j] != s[i] {
			delete(set, s[j])
			j++
		}
		j++
	}
	if len(set) > res {
		res = len(set)
	}

	return res
}
var lengthOfLongestSubstring = function(s) {
    let n = s.length;
    let set = new Set();
    let res = 0;
    let str = s.split('');
    for (let i = 0, j = 0; i < n; i++) {
        if (set.has(str[i])) {
            res = Math.max(res, set.size);
            while (j < n && str[j] !== str[i]) {
                set.delete(str[j++]);
            }
            j++;
        } else {
            set.add(str[i]);
        }
    }
    res = Math.max(res, set.size);
    return res;

};
function lengthOfLongestSubstring(s: string): number {
    let n = s.length;
    let set = new Set<string>();
    let res = 0;
    let str = s.split('');
    for (let i = 0, j = 0; i < n; i++) {
        if (set.has(str[i])) {
            res = Math.max(res, set.size);
            while (j < n && str[j] !== str[i]) {
                set.delete(str[j++]);
            }
            j++;
        } else {
            set.add(str[i]);
        }
    }
    res = Math.max(res, set.size);
    return res;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值