Leetcode—3.Longest Substring Without Repeating Characters

来源:互联网 发布:安卓便签软件 编辑:程序博客网 时间:2024/06/06 16:25

3.Longest Substring Without Repeating Characters

@(LeetCode)
合肥最近阴雨绵绵,今天特别困,喝了一杯咖啡仍然没精神,只能刷道题提提神了。
题目描述:给定一个字符串,返回没有重复字符的最长子串的长度。
LeetCode官网
思路:
- 暴力搜索将不重复子串及其长度分别作为key-value放入map中;
- 对map按value进行降序排列,取出第一个value值即得到答案。

下面这个版本通过了Run Code,但是没通过提交,原因是时间复杂度过高,尤其是String长度比较大的时候:

    public int lengthOfLongestSubstring(String s) {        Map<String,Integer> map=new TreeMap<String,Integer>();        for(int i=0;i<s.length();i++){//将全部无重复子串放入map中,key=substr,value=length;            if (s.length()==1){                map.put(s,1);                break;            }            for(int j=i+1;j<s.length();j++){                if(s.substring(i,j).indexOf(s.charAt(j))!=-1){//if-新字符在子串中                    map.put(s.substring(i,j),s.substring(i,j).length());                    break;                }else if(s.substring(i,j).indexOf(s.charAt(j))==-1&&j==s.length()-1){//                    map.put(s.substring(i),s.substring(i).length());                }            }        }//        Iterator itemp=map.entrySet().iterator();//         while(itemp.hasNext()){//             Map.Entry pair=(Map.Entry)itemp.next();//             System.out.println(pair.getKey()+" = "+pair.getValue());//         }        //将map按照value降序,并取出第一个key,即为最长无重复子串        Comparator<Map.Entry<String,Integer>> valueComparator=new Comparator<Map.Entry<String,Integer>>(){            @Override            public int compare(Map.Entry<String,Integer> o1,Map.Entry<String,Integer> o2){                return o2.getValue()-o1.getValue();            }        };        List<Map.Entry<String,Integer>> list=new ArrayList<Map.Entry<String,Integer>>(map.entrySet());        Collections.sort(list,valueComparator);        Iterator itf=list.iterator();        if(itf.hasNext()){            Map.Entry pair=(Map.Entry)itf.next();            return (int)pair.getValue();        }else{            return 0;        }}

所以分析如何降低时间复杂度:我们发现,比如字符串为abcabcbb,当i=0,j=3时,字符串abca重复了,换言之,在j=3前,子字符串是不重复的,那下一次i=1,j3,这样减少了for的次数,降低了时间复杂度,提交正确。

class Solution {public int lengthOfLongestSubstring(String s) {        Map<String,Integer> map=new TreeMap<String,Integer>();        int a=1;        for(int i=0;i<s.length();i++){//将全部无重复子串放入map中,key=substr,value=length;            if (s.length()==1){                map.put(s,1);                break;            }            if(i==a)a++;//避免"aab"这种情况            for(int j=a;j<s.length();j++){                if(s.substring(i,j).indexOf(s.charAt(j))!=-1){//if-新字符在子串中                    a=j;                    map.put(s.substring(i,j),s.substring(i,j).length());                    break;                }else if(s.substring(i,j).indexOf(s.charAt(j))==-1&&j==s.length()-1){//                    map.put(s.substring(i),s.substring(i).length());                }            }        }//        Iterator itemp=map.entrySet().iterator();//         while(itemp.hasNext()){//             Map.Entry pair=(Map.Entry)itemp.next();//             System.out.println(pair.getKey()+" = "+pair.getValue());//         }        //将map按照value降序,并取出第一个key,即为最长无重复子串        Comparator<Map.Entry<String,Integer>> valueComparator=new Comparator<Map.Entry<String,Integer>>(){            @Override            public int compare(Map.Entry<String,Integer> o1,Map.Entry<String,Integer> o2){                return o2.getValue()-o1.getValue();            }        };        List<Map.Entry<String,Integer>> list=new ArrayList<Map.Entry<String,Integer>>(map.entrySet());        Collections.sort(list,valueComparator);        Iterator itf=list.iterator();//此处为List.iterator()        if(itf.hasNext()){            Map.Entry pair=(Map.Entry)itf.next();            return (int)pair.getValue();          }else{            return 0;        }    }}

中途看到的知识点:
- 迭代Map中的键值对时,通常是获得map.entrySet().iterator()。为什么?因为Map接口中没有迭代器,Java中最基本的集合接口是Collection,Set和List继承Collection,Collection中声明了一些通用方法,其中就包括了iterator(),所以Set和List可以使用迭代器,而Map中并没有迭代器。而Map中声明了一个内部接口Map.Entry

public static void printMap(Map mp) {    Iterator it = mp.entrySet().iterator();    while (it.hasNext()) {        Map.Entry pair = (Map.Entry)it.next();        System.out.println(pair.getKey() + " = " + pair.getValue());        it.remove(); // avoids a ConcurrentModificationException    }}
  • String中常用方法,length(),charAt(),indexOf(),substring(begin,end)等

中途遇到的小bug:
- LeetCode提示leetcode Status: Time Limit Exceeded,如果运行出现这个问题很可能是程序出现了死循环,如果运行没问题而提交出现这个问题,很可能是程序的复杂度太高,因为提交时会使用长度比较大的例子来测试,复杂度太高会不通过。
- 如上面代码段所示,it.next()执行完,迭代器it会指向Set中下一个元素,也就是下一个键值对。而mp.entrySet().iterator()始终是指向第一个元素也就是第一个键值对,这是不变的。我在这里遇到了个小bug,因为我在排序时是将键值对放入了list中,后来迭代器应该针对list,而我一开始迭代器还是为mp.entrySet().iterator(),所以输出始终是原来map中的第一个值,结果错误了。

阅读全文
0 0
原创粉丝点击