2022/3/17leetcode每日一题——词典中最长的单词(字典树解法)

leetcode题目:

给你一个字符串数组words,请你找出words中最长的一个单词且该单词要是由数组中其他单词添加一个字母而来的。若其中有多个可行的答案,则返回答案中字典序最小的单词。若无答案,则返回空字符串。

例子:输入:words = [“w”,“wo”,“wor”,“worl”, “world”]
输出:“world”
解释: 单词"world"可由"w", “wo”, “wor”, 和 "worl"逐步添加一个字母组成。

输入:words = [“a”, “banana”, “app”, “appl”, “ap”, “apply”, “apple”]
输出:“apple”
解释:“apply” 和 “apple” 都能由词典中的单词组成。但是 “apple” 的字典序小于 “apply”

解析

常规解法:排序+HashSet

我们可以先对整个字符串数组进行排序(字符串之间的排序是从左往右按每个字母的字典序大小进行排列,直到一方没有字符为止)。
代码:

public String findLongestWord(String[] words){
	Arrays.sort(words);
	String result = "";
	Set<String> set = new HashSet();
	for(String s : words){
		if(s.length() == 1 || set.contains(s.substring(0,s.length()-1)){
			result = s.length() > result.length() ? s : result;
			set.add(s);
		}
	}
	return result;
}

排序+字典树(前缀树)解法

什么是字典树

字典树 (Trie),又称单词查找树、前缀树,是一种树形结构。
字典树的性质:
1.根节点不包含字符,除根节点外每一个节点都只包含一个字符;
2.从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串;
3.每个节点的所有子节点包含的字符都不相同。
如图:字典树储存 “a”、“apple”、“appeal”、“appear”、“bee”、“beef”、“cat” 这 7 个单词。
在这里插入图片描述
字典树的基础代码:

class TrieNode{
        boolean exsit;		//表示以该字母为最后一个字母的单词是否存在
      //int count;  		//可以用来表示以该字符串为前缀的单词总数
        TrieNode[] children;
        
        TrieNode(){
            exsit = false;
            children = new TrieNode[26];
        }
    }
class Trie{
        TrieNode root;
        
        Trie(){
            this.root = new TrieNode();
        }
        public void insert(String s){
            TrieNode temp = root;
            for(char c : s.toCharArray()){
                if(temp.children[c-'a'] == null){
                    temp.children[c-'a'] = new TrieNode();
                }
                temp = temp.children[c-'a'];
            }
            //表示字典树中存在s字符串
            temp.exsit = true;
        }
        public boolean inDictionary(String s){
            TrieNode temp = root;
            for(int i = 0 ; i < n ; i++){
				char c = s.charAt(i);
				temp = temp.children[c-'a'];
				if(temp == null){
					return false;
				}
				if(i == n-1 && temp.exsit == false){
					return false;
				}
			}
            return true;
        }
    }

字典树的应用场景

①用于字典: 字符串集合
②计算热词: 统计字符串在集合中出现的个数(寻找以某个字符串为前缀的单词总数)
③串的快速检索 给出 N 个单词组成的熟词表,以及一篇全用小写英文书写的文章,按最早出现的顺序写出所有不在熟词表中的生词。可以把熟词建成字典树,然后读入文章进行比较,这种方法效率是比较高的。(HashSet也可以)
④“串”排序 :给定N个互不相同的仅由一个单词构成的英文名,将他们按字典序从小到大输出,采用数组的方式创建字典树,这棵树的每个结点的所有儿子很显然地按照其字母大小排序。对这棵树进行先序遍历即可。(CompareTo方法也可以)
⑤最长公共前缀:对所有串建立字典树,对于两个串的最长公共前缀的长度即他们所在的结点的公共祖先个数,于是,问题就转化为当时公共祖先问题。

回归题目

学习完字典树的知识,我们再来回归题目。题目要求找出最长的单词且该单词是由数组中的字符串一步一步构建的。
代码如下:

public String longestWord(String[] words) {
        Arrays.sort(words);
        Trie trie = new Trie();
        String result = "";
        for(String s : words){
            trie.insert(s);
            if(trie.search(s.substring(0,s.length()-1) && s.length() > result.length()){
                result = s;
            }
        }
        return result;
    }
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值