zoukankan      html  css  js  c++  java
  • 无重复字符的最长子串

    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的值。

  • 相关阅读:
    常见 Web 安全攻防总结
    传统方式接口测试返回值json验证
    Springboot中RestTemplate -- 用更优雅的方式发HTTP请求
    mock简单的json返回
    MySQL数据库学习笔记(五)----MySQL字符串函数、日期时间函数
    MySQL数据库学习笔记(四)----MySQL聚合函数、控制流程函数(含navicat软件的介绍)
    MySQL数据库学习笔记(三)----基本的SQL语句
    MySQL数据库学习笔记(一)----MySQL 5.6.21的安装和配置(setup版)
    python实现广度优先搜索
    php递归
  • 原文地址:https://www.cnblogs.com/yh-simon/p/12818854.html
Copyright © 2011-2022 走看看