524. Longest Word in Dictionary through Deleting

Given a string and a string dictionary, find the longest string in the dictionary that can be formed by deleting some characters of the given string. If there are more than one possible results, return the longest word with the smallest lexicographical order. If there is no possible result, return the empty string.

Example 1:
Input:
s = "abpcplea", d = ["ale","apple","monkey","plea"]

Output: 
"apple"
Example 2:
Input:
s = "abpcplea", d = ["a","b","c"]

Output: 
"a"
Note:
All the strings in the input will only contain lower-case letters.
The size of the dictionary won't exceed 1,000.
The length of all the strings in the input won't exceed 1,000.



524. Longest Word in Dictionary through Deleting


https://leetcode.com/problems/longest-word-in-dictionary-through-deleting/solution/

Solution 1 : 

* Time complexity : O(2^n). generate calls itself 2^n  times. Here, n refers to the length of string s

* Space complexity : O(2^n) list 




class Solution {
    // get all the possiblitlies from s ,and check if any of them is in the dictionary, 
    // if there is one, we want to get the longest and if the length is the same, we want to 
    // get the smallest by lexicographical order. 
    
    // the way to get all possibilites is do dfs on the string s, 
    // there are s.length() levels , on each level, we either pick the current char , or we don't 
    
    public String findLongestWord(String s, List<String> d) {
        HashSet<String> set = new HashSet<>(d); // transform a list of strings into a set of strings 
        List<String> list = new ArrayList<>();
        dfs(list, "", s, 0);
        String res = "";
        for(String str : list){
            if(set.contains(str)){
                // use stringX.compareTo(stringY) < 0, when stringX has smaller order 
                if(str.length() > res.length() || (str.length() == res.length() && str.compareTo(res) < 0 )){
                    res = str; // pass a string 
                }
                
            }
        }
        return res;
    }
    private void dfs(List<String> list, String cur, String s, int level){
        // base case 
        if(level == s.length()){
            list.add(cur);
            return;
        }
        
        // pick current char 
        dfs(list, cur + s.charAt(level), s, level + 1);
        // not pick current char
        dfs(list, cur, s, level + 1);
        
    }
}



Solution 2 : 


Algorithm
The matching condition in the given problem requires that we need to consider the matching string in the dictionary with the longest length and in case of same length, the string which is smallest lexicographically. To ease the searching process, we can sort the given dictionary's strings based on the same criteria, such that the more favorable string appears earlier in the sorted dictionary.


Sort the list, check if every word in the list is a subsequence of the string s, once we find one, return , because its the best one 

if a word can be formed thru deletion of s, then the word is also a subsequence of s 




* Time complexity : O(n*x*logn + n*x)

 Here n refers to the number of strings in list d

 and x refers to average string length. Sorting takes O(nlogn)

 and isSubsequence takes O(x) to check whether a string is a subsequence of another string or not.

* Space complexity : O(logn)

 Sorting takes O(logn) space in average case.






class Solution {
    public String findLongestWord(String s, List<String> d) {
        Collections.sort(d, new Comparator<String>(){
            @Override 
            public int compare(String a, String b){
                if(a.length() == b.length()){
                    return a.compareTo(b);
                }else{
                    if(a.length() > b.length()){
                        return -1;
                    }else if(a.length() < b.length()){
                        return 1;
                    }else{
                        return 0;
                    }
                }
            }
        });
        for(String str : d){
            if(isSubsequence(str, s)){
                return str;
                
            }
        }
        return "";
        
    }
    private boolean isSubsequence(String str, String s){
        int i = 0;
        for(char c : s.toCharArray()){
            if(i < str.length() && c == str.charAt(i)) i++;
        }
        return i == str.length();
        
    }
}




Solution 3 : 

Without Sorting

Since sorting the dictionary could lead to a huge amount of extra effort, we can skip the sorting and directly look for the strings  x in the unsorted dictionary d such that x is a subsequence in s. If such a string x is found, we compare it with the other matching strings found till now based on the required length and lexicographic criteria. Thus, after considering every string in d, we can obtain the required result.


* time complexity : O(n*x) One iteration over all strings is required. Here n refers to the number of strings in list d and x refers to average string length.

* Space complexity : O(x)
max_str variable is used.




class Solution {
    public String findLongestWord(String s, List<String> d) {
        String res = "";
        for(String str : d){
            if(isSubsequence(str, s)){
                if(res.length() < str.length() || (str.length() == res.length() && str.compareTo(res) < 0)){
                    res = str;
                }
            }
        }
        return res;
    }
    private boolean isSubsequence(String str, String s){
        int i = 0;
        for(char c : s.toCharArray()){
            if(i < str.length() && str.charAt(i) == c) i++;
        }
        return i == str.length();
    }
}
相關文章
相關標籤/搜索