zoukankan      html  css  js  c++  java
  • [leetcode]_Longest Substring Without Repeating Characters

    问题:求一个字符串中最长不重复子串的长度。

    直接思路:以每个字符为出发计算最长不重复子串。TLE。O(n2),HashMap存储字符出现的位置。

    代码: 

     1    public int lengthOfLongestSubstring(String s) {
     2         Map<Character , Integer> temp = new HashMap<Character , Integer>();
     3         int len = s.length();
     4         int tempLen = 0,maxLen = 0;
     5         int i = 0;
     6         while(i < len){
     7             char ch = s.charAt(i);
     8             temp.put(ch , i);
     9             tempLen = 1;
    10             for(int j = i + 1 ; j < len ; j++){
    11                 char ch2 = s.charAt(j);
    12                 if(!temp.containsKey(ch2)) {
    13                     temp.put(ch2 , j);
    14                     tempLen++;
    15                 }else{
    16                     if(tempLen > maxLen) maxLen = tempLen;
    17                     //这里我还很得意,下次从重复的字符的下一位开始,但是依旧是TLE
    18                     i = temp.get(ch2) + 1;
    19                     temp.clear();
    20                     break;
    21                 }
    22             }
    23         }
    24         return maxLen;
    25     }

    提交了很多次依旧TLE。不得其解,求助之。

    网络上解题思路与我是一样的,当遇到重复字符时,下次再计算最长子串时从重复字符的下一个字符开始,但是为什么会TLE呢?经分析别人的代码后,发现。

    这个思路没问题,TLE的原因在于原先判断重复地方后,在里层for循环重复计算了映射到map中的值(map中存储字符出现的位置,其实计算多少次值都是一样的),为了不重复计算此部分的map值,引入一个新的标记位start ,当重复位置在start之前时,对找最长子串不影响,直接更新map中的映射即可;当重复位置在start之后时,此时比较cur - start(此次的最长子串)是否能更新maxLen。这样将O(n2)优化为O(n)。

    public int lengthOfLongestSubstring(String s) {
            Map<Character , Integer> hash = new HashMap<Character , Integer>();
            
            int len = s.length();
            int maxLen = 0,start = 0;
            for(int i = 0 ; i < len ; i++){
                char ch = s.charAt(i);
                if(!hash.containsKey(ch)){
                    hash.put(ch , i);
                }else{
                    int last = hash.get(ch);
                    if(last < start) hash.put(ch , i);
                    //如果该字符上次出现的位置在start之前,对结果不产生影响,相当于这个位置已经被废掉的,直接更新即可。
    
                    else{
                        if(i - start > maxLen) maxLen = i - start;
                        hash.put(ch , i);
                        start = last + 1;
                        //将start的位置更新为重复位置的下一位
                    }
                }
            }
            if(len - start > maxLen) maxLen = len - start;
            //循环结束时,需要对最后一个不重复子串的长度进行判断
    
            return maxLen;
        }

    另一个优化地方:

    上面代码使用Map来存储字符出现位置,这里可用数组来模拟HashMap提高效率。申请一个int[] hashTable = new int[256];将其初始化为-1。256个包含了ASCII码表所有字符,之后遇见统计字符数量什么的,可参考这种方法。

    提交后RunTime从528ms -> 424ms。

  • 相关阅读:
    简单的实现了利用plist进行大图分割小图
    windows 10升级后系统盘清理
    在window下用编译lua源文件生成lua程序
    window下ip切换
    springMVC对简单对象、Set、List、Map的数据绑定和常见问题.
    MIME类型大全
    Apache poi 固定Excel 表格导入数据库方法(列名对应数据库字段名)
    java 通过Apache poi导出excel代码demo实例
    mySQL 开启事件存储过程
    Mysql 变量讲解
  • 原文地址:https://www.cnblogs.com/glamourousGirl/p/3757295.html
Copyright © 2011-2022 走看看