【算法面试宝典】无重复字符的最长子串

1 算法描述

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

示例 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 由英文字母、数字、符号和空格组成

2 解题思路

解法一:暴力破解

思路:以字符串中的每一个字符作为起点,依次遍历字符串中起点字符右侧的字符,如果没有重复就放入HashSet中,如果字符和HashSet中的字符有重复就记录HashSet的长度,和最长长度比较,保留最长长度,依次类推,直到所有的字符遍历完,最终得到最长子串长度。

示例:String s = "abcabcdb";

遍历得到的子串有:"abc","bca","cab","abcd","","bcd","cdb","db"

很容易看到最长子串为 "abcd"。

这种解法的时间复杂度是O(n^2),空间复杂度是O(n)。

编码如下:

    public static int subString2(String s){
        int ans = 0;//最大长度
        HashSet<Character> occ = new HashSet<Character>();//存储无重复字符串
        for(int i=0;i<s.length()-1;i++){
            occ.add(s.charAt(i));
            for (int j=i+1;j<s.length() && !occ.contains(s.charAt(j));j++){
                    occ.add(s.charAt(j));
            }
            ans = Math.max(occ.size(),ans);
            occ.clear();
        }
        return ans;
    }

解法二:使用滑动窗口

思路:使用HashSet来存储滑动窗口中的字符,遍历字符串中的字符,滑动窗口有左指针 left 和右指针 right,right 向右移动,指向的元素判断是否在HashSet中有重复的元素,如果没有就把该元素放入滑动窗口中,如果有就把重复元素左侧所有的元素移除滑动窗口,即left指针向右移动,知道没有重复元素。记录每次滑动窗口的长度,最长的即为无重复字符最长子串的长度。解题过程如下所示:

 

 可以看到最长子串在第六步产生,此时滑动窗口中的字符有 a b c d,长度是4。

编码实现:编码实现有很多种方式,每个人的风格都不一样,这里提供两种编码风格

编码一:

    public static int subString(String s){
        HashSet<Character> occ = new HashSet<Character>();
        int left = 0;//滑动窗口的左指针
        int right = 0;//滑动窗口的右指针
        int ans = 0;//最长子串的长度
        while(left<=right && right<s.length()){
            if (!occ.contains(s.charAt(right))){
                occ.add(s.charAt(right++));
                ans = Math.max(ans,right-left);
            } else {
                occ.remove(s.charAt(left++));
            }
        }
        return ans;
    }

编码二:

    public static int subString(String s){
        HashSet<Character> occ = new HashSet<Character>();
        int left = 0;//滑动窗口的左指针
        int right = 0;//滑动窗口的右指针
        int ans = 0;//最长子串的长度
        for(int i=0;i<s.length();i++) {
            char t = s.charAt(i);
            while (occ.contains(t)) {
                occ.remove(s.charAt(left++));
            }
            occ.add(t);
            right++;
            ans = Math.max(ans,right-left);
        }
        return ans;
    }

这种解题方式时间复杂度是 O(n),空间复杂度是O(n)。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值