[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。

 

posted on 2014-05-28 16:14  匡匡锵锵  阅读(130)  评论(0编辑  收藏  举报

导航

AmazingCounters.com