392 是一个easy题, 就是问 s 是否能由t 构成。 当然不能把 t 的 所有2^n个子串都拿出来,一一和s比较。 只需要two points就行了。

Example 1:
s = "abc", t = "ahbgdc"

 

这道题很简单,但写出的code 可能差别很大,看看我第一次提交的code 和最新的code 差别就知道。


这个题还有 follow up 的解法: 思路就是把T的每个字母当作key,字母所在的index加入list作为value,然后就利用二分搜索来找s中某个字母的下一个位置。

 

521 是目前遇到的leetcode 上最扯淡的题,但很有启发性,不要小看这个问题,让你思考两个string 最长的 Uncommon Subsequence

算法: 如果字符串一样,不存在,如果字符串不同,则长的那一个。

 

522 把两个字符串扩展成 N 个字符串

这是一个非常优秀的题目,真的非常喜欢,因为几个解法都很有启发性。

算法一:  纯粹暴力解 (暴力解),会TLE, 我竟然花了一个多小时去写了code , code 写的特别丑。

把每个字符串的subsequence 全部求出来, 复杂度是 2^n。 参考 78 subsets写一个backtracking 的算法。

得到 N 个 2^n 字符串, 然后两两进行比较,找出没有dupilicate 的最长的子串。复杂度竟然达到了 2^N * 2^N ,不超时才怪。

 

算法二: 优化暴力 算法 backTracking  + hashMap(优化):

 把得到的字符串全部存入 hashMap, hashMap 的value 存 Frequence, 如果 Frequence >1, 说明字符串重复, 所以在 Frequence ==1 的key 中找到 最长的那一个就行了. 

code如下, 涉及遍历 hashmap ,给出了两个方法,希望记牢。

    public int findLUSlength(String[] strs) {
        Map<String, Integer> map = new HashMap<>();
        
        for(String str: strs){
            getSubString(0, str,map, new StringBuilder());
        }
        
        int ans = -1;
       
        /*
        for(String s:  map.keySet()){
            if(map.get(s) == 1){
                ans  = Math.max(ans, s.length());
            }
        }*/
        
        
        for(Map.Entry<String,Integer> entry: map.entrySet()){
            if(entry.getValue() ==1) {
                ans = Math.max(ans,entry.getKey().length());
            }
            
        }
        return ans;      
    }
    
     void getSubString(int start, String str, Map<String,Integer> result, StringBuilder sb) {    
         
         result.put(sb.toString(), result.getOrDefault(sb.toString(),0)+1);
      
         for(int i= start; i< str.length(); i++){
             sb.append(str.charAt(i));
             getSubString(i+1,str,result,sb);
             sb.setLength(sb.length()-1);
         }   
    }

 

 

 

算法三:

通过观察分两种情况

1) 如果字符串全部不一样,那取最长的那一个。

2)如果 很多相同的, 例如 aabb, aabb,  aa, ab, 那结果只能返回 -1了。

算法: 从上面观察出结论:answer 是 N个字符串某个字符串,这个字符串不是别人的subsequence, 这就用到391的算法了。

391 算法的复杂度是 len, len 是字符串的长度, 需要两两比较, 因此总的复杂度是 len*N^2. N是字符串的个数。

 

写code 时遇到一个坑: WA 了这组数据 ["a","b","c","d","e","f","a","b","c","d","e","f"]

把 "a " 和整个数组比较,一定要设置flag.发现 "a" 不是别人的 subSequence 时 才和max_len 进行比较。

 

算法的复杂度为  len *N2

 

 

算法四: 算法三的改进版:

先排序,按照长度从长到短排列, 从最长的开始找,当找到某个长度问L, 并且 只需要在同样长度L 字符串中比较 是否是某个的subsequence, 因为当 L1> L2 时, L1 一定不是L2的subsequence. 

PS: 有时为了把循环里逻辑不要搞那么复杂,多循环几次没啥不好的。

比如最优化的循环写法:

        for(int i=0; i<strs.length; i++){
            String s = strs[i]; 
            boolean flag = true;
            for(int j=0; j<strs.length; j++){
                if(i!=j ){
                    if(s.length()> strs[j].length()) return s.length();
                    else if(isSubsequence(s, strs[j])) {flag = false; break;}
                }
            }
            if(flag) return s.length();
        }

 

但其实没必要,判断那么充分,完整的code 清晰的写法:

        //Arrays.sort(strs, (o1,o2)->(o2.length()-o1.length()));
        Arrays.sort(strs, new Comparator < String > () {
            public int compare(String s1, String s2) {
                return s2.length() - s1.length();
            }
        });
    
        for(int i=0; i<strs.length; i++){
            String s = strs[i]; 
            boolean flag = true;
            for(int j=0; j<strs.length; j++){
                if(i==j) continue;
                if(isSubsequence(s, strs[j])) {flag = false; break;}
            }
            if(flag) return s.length();
        }
        
        return -1;
        
    }
    
    boolean isSubsequence(String s, String t){
        int index_s=0, index_t=0;
        while(index_s < s.length() && index_t < t.length()){
            if(s.charAt(index_s) == t.charAt(index_t)) {
                index_s ++;
            }
            index_t++;
        }
        
        if(index_s == s.length()) return true;
        return false;
    }

 

还有一个问题百思不得其解:为何排序的简略写法 效率会很低呢? 第一个一行排序竟然需要32ms, 而第二个才1ms, 差别在哪?

        //Arrays.sort(strs, (o1,o2)->(o2.length()-o1.length()));
        Arrays.sort(strs, new Comparator < String > () {
            public int compare(String s1, String s2) {
                return s2.length() - s1.length();
            }
        });

 

524  就是从字典里找出 是 给出字符串s 的subsequence , 完全用到392写法,只是需要排序。

排序要求: 按照字符串长度从长到短,相同长度下 按照 字典序排列。

    public String findLongestWord(String s, List<String> d) {
        if(d == null || s ==null ) return "";
        
        Collections.sort(d,(o1,o2)->o2.length()==o1.length()? o1.compareTo(o2) : o2.length()-o1.length());
       // for(String str: d) System.out.println(str);
        for(String t: d){
            if(isSubsequence(s,t)) return t;
        }
        
        
        return "";
    }
    
    boolean isSubsequence(String s, String t) {
        
        int index_t=0;
        int index_s=0;
        while(index_s <s.length() && index_t <t.length() ){
            if(s.charAt(index_s) == t.charAt(index_t) ) index_t ++;
            index_s++;
        }
        
        if(index_t == t.length()) return true;
        return false;
    }

 

posted on 2019-09-27 15:33  KeepAC  阅读(139)  评论(0编辑  收藏  举报