leetcode 720. Longest Word in Dictionary

Given a list of strings words representing an English Dictionary, find the longest word in words that can be built one character at a time by other words in words. If there is more than one possible answer, return the longest word with the smallest lexicographical order.

If there is no answer, return the empty string.

Example 1:

Input:
words = ["w","wo","wor","worl", "world"]
Output: "world"
Explanation:
The word "world" can be built one character at a time by "w", "wo", "wor", and "worl".

Example 2:

Input:
words = ["a", "banana", "app", "appl", "ap", "apply", "apple"]
Output: "apple"
Explanation:
Both "apply" and "apple" can be built from other words in the dictionary. However, "apple" is lexicographically smaller than "apply".

Note:

  • All the strings in the input will only contain lowercase letters.
  • The length of words will be in the range [1, 1000].
  • The length of words[i] will be in the range [1, 30].

本质上是trie!前缀树!

class Solution(object):
    def longestWord(self, words):
        """
        :type words: List[str]
        :rtype: str
        """
        # use greey algo
        words_set = set([""])
        words.sort()
        ans = ""
        for word in words:
            if word[:-1] in words_set:
                if len(word) > len(ans):
                    ans = word
                words_set.add(word)
        return ans
class Node(object):
    def __init__(self, val=""):
        self.val = val
        self.subs = collections.defaultdict(Node)

class Trie(object):
    def __init__(self):
        self.root = Node("")

    def insert(self, s):
        node = self.root
        for c in s:
            node = node.subs[c]
        node.val = s

    def longest_word(self):
        self.ans = ""
        def dfs(node):
            for k, n in node.subs.items():
                if n.val:
                    if len(n.val)>len(self.ans) or (len(n.val)==len(self.ans) and n.val<self.ans):
                        self.ans = n.val
                    dfs(n)
        dfs(self.root)
        return self.ans

class Solution(object):
    def longestWord(self, words):
        """
        :type words: List[str]
        :rtype: str
        """
        trie = Trie()
        for word in words:
            trie.insert(word)
        return trie.longest_word()        

注意:Trie每个结点的子树的根节点的组织方式有几种。

1>如果默认包含所有字符集,则查找速度快但浪费空间(特别是靠近树底部叶子)。

2>如果用链接法(如左儿子右兄弟),则节省空间但查找需顺序(部分)遍历链表。

3>alphabet reduction: 减少字符宽度以减少字母集个数。

4>对字符集使用bitmap,再配合链接法。

Trie的插入和查找算法:

def find(node, key):
    for char in key:
        if char in node.children:
            node = node.children[char]
        else:
            return None
    return node.value == key
algorithm insert(root : node, s : string, value : any):
    node = root
    i    = 0
    n    = length(s)

    while i < n:
        if node.child(s[i]) != nil:
            node = node.child(s[i])
            i = i + 1
        else:
            break

    (* append new nodes, if necessary *)
    while i < n:
        node.child(s[i]) = new node
        node = node.child(s[i])
        i = i + 1

    node.value = value
class TrieNode(object):
    def __init__(self):
        self.children=collections.defaultdict(TrieNode)
        self.isEnd=False
        self.word =‘‘

class Trie(object):
    def __init__(self):
        self.root=TrieNode()

    def insert(self, word):
        node=self.root
        for c in word:
            node =node.children[c]
        node.isEnd=True
        node.word=word

    def bfs(self):
        q=collections.deque([self.root])
        res=‘‘
        while q:
            cur=q.popleft()
            for n in cur.children.values():
                if n.isEnd:
                    q.append(n)
                    if len(n.word)>len(res) or n.word<res:
                        res=n.word
        return res 

class Solution(object):
    def longestWord(self, words):
        trie = Trie()
        for w in words: trie.insert(w)
        return trie.bfs()

java的解法:

Build a trie in the normal way, then do a dfs to find the longest continuous downward path from the root. This is not a particularly hard question in the context of trie, the point of this solution is to present a generic way of trie building and inserting that can be easily adapted to similar questions. Code:

class Solution {
    public String longestWord(String[] words) {
        TrieNode root = new TrieNode ();
        root.word = "-";
        for (String word : words)
            root.insert (word);
        return dfs (root, "");
    }

    String dfs (TrieNode node, String accum) {
        if (node == null || node.word.length () == 0)
            return accum;
        String res = "";
        if (!node.word.equals ("-"))
            accum = node.word;
        for (TrieNode child : node.links) {
            String curRes = dfs (child, accum);
            if (curRes.length () > res.length () || (curRes.length () == res.length () && curRes.compareTo (res) < 0))
                res = curRes;
        }
        return res;
    }

    /* Hand write this class every time you need to so you can remember well */
    static class TrieNode {
        String word = "";
        TrieNode[] links = new TrieNode[26];

        void insert (String s) {
            char[] chs = s.toCharArray ();
            TrieNode curNode = this;
            for (int i = 0; i < chs.length; i++) {
                int index = chs[i] - ‘a‘;
                if (curNode.links[index] == null)
                    curNode.links[index] = new TrieNode ();
                curNode = curNode.links[index];
            }
            curNode.word = s;
        }
    }
}

A typical trie for the list of "ab", "ac":

class Solution {
    class TrieNode {
        TrieNode[] children;
        boolean isWord;
        String word;

        public TrieNode() {
            children = new TrieNode[26];
        }
    }

    class Trie {
        private TrieNode root;

        public Trie() {
            root = new TrieNode();
        }

        public void insert(String word) {
            TrieNode node = root;
            for (int i = 0; i < word.length(); i++) {
                int idx = word.charAt(i) - ‘a‘;
                if (node.children[idx] == null) {
                    node.children[idx] = new TrieNode();
                }
                node = node.children[idx];
            }
            node.isWord = true;
            node.word = word;
        }

        public String findLongestWord() {
            String result = null;
            Queue<TrieNode> queue = new LinkedList<>();
            queue.offer(root);
            while (!queue.isEmpty()) {
                int size = queue.size();
                for (int i = 0; i < size; i++) {
                    TrieNode node = queue.poll();
                    for (int j = 25; j >= 0; j--) {
                        if (node.children[j] != null && node.children[j].isWord) {
                            result = node.children[j].word;
                            queue.offer(node.children[j]);
                        }
                    }
                }
            }
            return result;
        }
    }

    public String longestWord(String[] words) {
        Trie trie = new Trie();
        for (String word : words) {
            trie.insert(word);
        }

        return trie.findLongestWord();
    }
}

原文地址:https://www.cnblogs.com/bonelee/p/8831114.html

时间: 2024-08-26 11:31:39

leetcode 720. Longest Word in Dictionary的相关文章

[leetcode]720. Longest Word in Dictionary字典中最长的单词

b.compareTo(a) 这个函数是比较两个值得大小,如果b比a大,那么返回1 如果小,那么返回-1,相等返回0 如果比较的是字符串,那么比较字典编纂顺序,b靠前返回-1,靠后返回1 这个题的核心虽然是hashtable,但是这个方法还是很重要的,因为自己实现比较字符串很麻烦 /* 用一个Hashset来判断子串是不是在集合里 然后遍历出最长的就行 长度相同的用compareTo方法判断谁的字典顺序靠前 这个题最难的感觉其实是不知道compareTo方法,自己实现还挺麻烦的 */ publi

[LeetCode] 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 lexicographic

[LeetCode] 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 lexicographic

[LeetCode] Longest Word In Dictionary

Given a list of strings words representing an English Dictionary, find the longest word in words that can be built one character at a time by other words in words. If there is more than one possible answer, return the longest word with the smallest l

Hash Table-720. Longest Word in Dictionary

Given a list of strings words representing an English Dictionary, find the longest word in words that can be built one character at a time by other words in words. If there is more than one possible answer, return the longest word with the smallest l

524. Longest Word in Dictionary through Deleting

https://leetcode.com/problems/longest-word-in-dictionary-through-deleting/#/solutions An alternate, more efficient solution which avoids sorting the dictionary: public String findLongestWord(String s, List<String> d) { String longest = "";

[CareerCup] 18.7 Longest Word 最长的单词

5.7 Given a list of words, write a program to find the longest word made of other words in the list. 这道题给了我们一个字符串数组,让我们找到最长的那个单词是由字符串数组中的其他单词组成的,LeetCode上跟类似的题目有Word Break和Word Break II.那么我们首先来想如果是拆分两个单词怎么做,那我们要首先把所有的单词存到哈希表里,然后遍历每个单词,每个位置上都拆分成左右两个字符

【LeetCode OJ】Word Ladder I

Problem Link: http://oj.leetcode.com/problems/word-ladder/ Two typical techniques are inspected in this problem: Hash Table. One hash set is the words dictionary where we can check if a word is in the dictionary in O(1) time. The other hash set is us

LeetCode OJ - Longest Consecutive Sequence

这道题中要求时间复杂度为O(n),首先我们可以知道的是,如果先对数组排序再计算其最长连续序列的时间复杂度是O(nlogn),所以不能用排序的方法.我一开始想是不是应该用动态规划来解,发现其并不符合动态规划的特征.最后采用类似于LRU_Cache中出现的数据结构(集快速查询和顺序遍历两大优点于一身)来解决问题.具体来说其数据结构是HashMap<Integer,LNode>,key是数组中的元素,所有连续的元素可以通过LNode的next指针相连起来. 总体思路是,顺序遍历输入的数组元素,对每个