无重复字符的最长子串

image-20200502165227538

暴力解法

思路很简单,依次计算从各个字符开始的无重复子串的长度,时间复杂度O(n^2)

   /**
     * 暴力求解
     * 261ms   7%
     * 40M     5%
     * @param s
     * @return
     */
    public int lengthOfLongestSubstring(String s){
        int ans=0;
        for(int i=0;i<s.length();i++){
            String sub="";
            for(int j=i;j<s.length();j++){
                if(sub.contains(String.valueOf(s.charAt(j)))){
                    break;
                }else{
                    sub= s.substring(i, j+1);
                    ans=Math.max(ans, sub.length());
                }
            }
        }
        return ans;
    }

暴力解法优化

采用HashMap进行 判断是否重复步骤 优化

/**
     * 引用HashMap 进行contains比较  O(n^2)
     * 140ms  11%
     * 40M    5%
     * @param s
     * @return
     */
    public int lengthOfLongestSubstring2(String s){
        int ans=0;
        char[] chars = s.toCharArray();
        int len=chars.length;
        for(int i=0;i<len;i++){
            Map<Character,Integer> map=new HashMap<>();
            for(int j=i;j<len;j++){
                if(map.containsKey(chars[j])){
                    break;
                }else{
                    map.put(chars[j],1);
                    ans=Math.max(ans, map.size());
                }
            }
        }
        return ans;
    }

滑动窗口 降低时间复杂度

​ 以上两个解法的时间复杂度显然是 O(n^2) 参考大佬的思路,所以采用滑动窗口(左右指针)来降低复杂度 变为 O(n)

思路

  • 总体而言,遍历过程 保持区间[start,end]区间内字符不重复

  • 定义一个map存储<k,v> ,其中k为字符,v为字符位置+1,加1表示从字符位置的下一个才开始不重复。

  • 定义不重复子串的开始位置为start ,结束位置为end。

  • 随着end不断向后遍历,会遇到与[start,end]区间内字符相同的情况,此时将字符作为key,获取其value值,并更新start,此时[start,end]区间内依旧不存在重复字符。

  • 无论是否更新start,都会更新其map数据结构和结果ans。

  • 时间复杂度O(n)

代码

/**
     * 使用滑动窗口  O(n)
     * 6ms   85%
     * 40M    5%
     * @param s
     * @return
     */
    public int lengthOfLongestSubstring3(String s) {
        int ans=0;
        int len=s.length();
        Map<Character,Integer> map=new HashMap<>();
        for(int start=0,end=0;end<len;end++){
            char c=s.charAt(end);
            if(map.containsKey(c)){
                start=Math.max(map.get(c), start);
            }
            ans=Math.max(ans, end-start+1);
            map.put(s.charAt(end), end+1);
        }
        return ans;
    }

纠错及补充

  • 做题时,将map和list混淆,竟将map误认为key可以重复,就没想到通过key刷新value的值。

posted @ 2020-05-02 17:48  YH_Simon  阅读(167)  评论(0编辑  收藏  举报