LeetCode3 无重复字符的子串

题目:

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

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

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

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

示例 4:
输入: s = ""
输出: 0

提示:
0 <= s.length <= 5 * 104 
s 由英文字母、数字、符号和空格组成
Related Topics 哈希表 双指针 字符串 Sliding Window

方法

暴力法

  • 时间复杂度:O(n2)
  • 空间复杂度:O(n)
class Solution {
  public  int lengthOfLongestSubstring(String s) {
        int strLength = s.length();
        int max = 0;
        for(int i =0;i<strLength;i++)
            for(int j=i+1;j<=strLength;j++)
                if(!isRept(s,i,j)) max = Math.max(max,j-i);
        return max;
    }
    // 判断子字符串中是否有重复字符
    public  boolean isRept(String s,int begin,int end){
        Set<Character> charSet = new HashSet<>();
        for(int i=begin;i<end;i++){
            Character x = s.charAt(i);
            if(charSet.contains(x))return true;
            charSet.add(x);
        }
        return false;
    }
}

滑动窗口

用set保存已存在的字符,
如果end处的字符重复,就将start减1,每次去除一个滑动窗口头部的重复字符直到删除的重复值不存在
如果end处的字符不重复,证明字符串没有重复的,则对比最大值

  • 时间复杂度:O(n),n为字符串长度,可能为2n
  • 空间复杂度:O(n),
class Solution {
    public int lengthOfLongestSubstring(String s) {
        int start = 0;
        int end = 0;
        int res = 0;
        Set<Character> set = new HashSet<>();
        while(end<s.length()){
            if(set.contains(s.charAt(end))){
                set.remove(s.charAt(start));
                start++;
            }else{
                set.add(s.charAt(end));
                end++;
                res = Math.max(res,end-start);
            }
        }
        return res;
    }
}

滑动窗口优化版

用map记录已经遍历的字符,并记录当前字符在遍历过子串中最后的位置,从而一次定位到当end指针指向重复字符时的起始位置

  • 时间复杂度:O(n),n为字符串长度
  • 空间复杂度:O(n)
class Solution {
  public  int lengthOfLongestSubstring(String s) {
      Map<Character,Integer> map = new HashMap<>();
      int res = 0;
      for(int start=0,end=0;end<s.length();end++){
          if(map.containsKey(s.charAt(end))){
              start = Math.max(start,map.get(s.charAt(end)));
          }
          res = Math.max(res,end-start+1);
          map.put(s.charAt(end),end+1);
      }
      return res;
    }
}

滑动窗口优化版2

由于字符串的长度有限,我们可以用数组代替Map

  • 时间复杂度:O(n),n为字符串长度
  • 空间复杂度:O(128)
public class Solution {
    public int lengthOfLongestSubstring(String s) {
        int res = 0;
        int[] index = new int[128];
        for(int start=0,end=0;end<s.length();end++){
            start = Math.max(start,index[s.charAt(end)]);
            res = Math.max(res,end-start+1);
            index[s.charAt(end)] = end+1;
        }
        return res;
    }
}
Js版本:
  • 时间复杂度:O()
  • 空间复杂度:O()
var lengthOfLongestSubstring = function(s) {
    let start = 0,max = 0;
    const map = new Array(128);
    for(let r=0;r<s.length;r++){
        if(map[s[r]]!==undefined){
            start = Math.max(start,map[s[r]]);
        }
        max = Math.max(max,r-start+1);
        map[s[r]]=r+1;
    }
    return max;
};

滑动窗口优化版3

用数组保存无重复字符串
Js版本

  • 时间复杂度:O()
  • 空间复杂度:O()
var lengthOfLongestSubstring = function(s) {
    let max = 0;
    let arr  =[];
    for(let i=0;i<s.length;i++){
        let index = arr.indexOf(s[i]);
        if(index!=-1){
            arr.splice(0,index+1);
        }
        arr.push(s[i]);
        max = Math.max(max,arr.length);
    }
    return max;
};
posted @   你也要来一颗长颈鹿吗  阅读(33)  评论(0编辑  收藏  举报
编辑推荐:
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
阅读排行:
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
点击右上角即可分享
微信分享提示