• [英雄星球六月集训LeetCode解题日报] 第23日 字典树


    日报

    • 今天两题代码可以复用,直接字典树模板套进来,写个查询即可。

    题目

    一、 472. 连接词

    链接: 472. 连接词

    1. 题目描述

    1. 连接词

    难度:困难

    给你一个 不含重复 单词的字符串数组 words ,请你找出并返回 words 中的所有 连接词

    连接词 定义为:一个完全由给定数组中的至少两个较短单词组成的字符串。

    示例 1:

    输入:words = ["cat","cats","catsdogcats","dog","dogcatsdog","hippopotamuses","rat","ratcatdogcat"]
    输出:["catsdogcats","dogcatsdog","ratcatdogcat"]
    解释:"catsdogcats" 由 "cats", "dog" 和 "cats" 组成; 
         "dogcatsdog" 由 "dog", "cats" 和 "dog" 组成; 
         "ratcatdogcat" 由 "rat", "cat", "dog" 和 "cat" 组成。
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    示例 2:

    输入:words = ["cat","dog","catdog"]
    输出:["catdog"]
    
    • 1
    • 2

    提示:

    • 1 <= words.length <= 104
    • 0 <= words[i].length <= 30
    • words[i] 仅由小写字母组成
    • 0 <= sum(words[i].length) <= 105

    2. 思路分析

    • 先过一遍·words建立字典树。
    • 接下来我们定义一个查询方法:find_split_count(s),这个方法的作用是用words中的单词恰好拼接s,寻找最多能把word切几段。
    • 那么答案显然就是words中每个单词执行一遍这个函数,返回值>=2的单词就是答案。
    • 当我们用字典树的查找方法,从s头开始匹配,寻找到一个完整单词时,从这里把s切成两半s1,s2.
    • 显然s1在words中出现了,那么只要s2也在words中出现,那么这个s就是满足题意的字符串;s2也可本身不用出现,只需要它能用words中多个字符串拼起来即可。
    • 显然s2可以递归这个函数本身find_split_count(s2)
    • 右半部分返回值r>=1,加上左半部分本身是一个合法串,l=1,那么这个串已经满足题意,可以提前返回了。
    • 具体实现时,为了不疯狂切片,我们方法声明为find_split_count(s,start,n),start和n代表s从下标start开始匹配到n结束。
    • 一定注意最后返回时要判断cur.is_end,如果非结束,那说明匹配失败,返回0。

    3. 代码实现

    class TrieNode:
        def __init__(self,cnt=0):
            self.cnt = cnt 
            self.next = [None]*26
            self.is_end = False
        def insert(self, word: str) -> None:
            cur = self
            for c in word:
                i = ord(c)-ord('a')
                if not cur.next[i] :  # 没有这个字符
                    cur.next[i] = TrieNode()
                cur = cur.next[i]
                cur.cnt += 1
            cur.is_end = True
       
        def find_split_count(self,word,start,n):   
            if start == n:
                return 0
            cur = self
            m = 0
            for i in range(start,n):
                c = word[i]
                idx = ord(c) - ord('a')
                
                if not cur.next[idx]:
                    return 0
                cur = cur.next[idx]
                if cur.is_end:
                    m = self.find_split_count(word,i+1,n)+1
                    if m >= 2:
                        return m                
            return m if cur.is_end else 0
    
    class Solution:
        def findAllConcatenatedWordsInADict(self, words: List[str]) -> List[str]:
            trie = TrieNode()
            n = len(words)
            for word in words:
                trie.insert(word)
            # word='nuqhmfj'
            # print(trie.find_split_count(word,0,len(word)))
            return [word for word in words if trie.find_split_count(word,0,len(word)) >=2]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    二、 面试题 17.15. 最长单词

    链接: 面试题 17.15. 最长单词

    1. 题目描述

    面试题 17.15. 最长单词

    难度:中等

    给定一组单词words,编写一个程序,找出其中的最长单词,且该单词由这组单词中的其他单词组合而成。若有多个长度相同的结果,返回其中字典序最小的一项,若没有符合要求的单词则返回空字符串。

    示例:

    输入: ["cat","banana","dog","nana","walk","walker","dogwalker"]
    输出: "dogwalker"
    解释: "dogwalker"可由"dog"和"walker"组成。
    
    
    • 1
    • 2
    • 3
    • 4

    提示:

    • 0 <= len(words) <= 200
    • 1 <= len(words[i]) <= 100

    2. 思路分析

    • 这题和上题字典树部分代码完全一致。
    • 满足条件的单词判断一下长度和字典序即可。

    3. 代码实现

    class TrieNode:
        def __init__(self, cnt=0):
            self.cnt = cnt
            self.next = [None] * 26
            self.is_end = False
    
        def insert(self, word: str) -> None:
            cur = self
            for c in word:
                i = ord(c) - ord('a')
                if not cur.next[i]:  # 没有这个字符
                    cur.next[i] = TrieNode()
                cur = cur.next[i]
                cur.cnt += 1
            cur.is_end = True
    
        def find_split_count(self, word, start, n):
            if start == n:
                return 0
            cur = self
            m = 0
            for i in range(start, n):
                idx = ord(word[i]) - ord('a')
    
                if not cur.next[idx]:
                    return 0
                cur = cur.next[idx]
                if cur.is_end:
                    m = self.find_split_count(word, i + 1, n) + 1
                    if m >= 2:
                        # print(word[start:i + 1], word[i + 1:], m)
                        return m       
                        
            return m  if cur.is_end else 0
            
    class Solution:
        def longestWord(self, words: List[str]) -> str:
            ans = ''
            m = 0
            trie = TrieNode()
    
            for word in words:
                trie.insert(word)
            for word in words:
                n = len(word)
                if trie.find_split_count(word,0,n)>=2:
                    if n > m :
                        m = n
                        ans = word
                    elif n == m and word < ans:
                        ans = word
            return ans
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
  • 相关阅读:
    macOS鼠标管理操作增强BetterMouse简体中文
    PHP 文件操作
    推荐 5 个 火火火火 的 CSS 项目
    Macos必备ps 磨皮滤镜插件
    2022.11.24线上笔试题
    四参数旋转角异常,平面坐标方位角不准确的问题
    react高阶成分(HOC)例子展示
    2434: 【区赛】[慈溪2013]统计方格
    PowerBI-窗口函数-INDEX
    S32K324芯片学习笔记-实时控制系统-ADC
  • 原文地址:https://blog.csdn.net/liuliangcan/article/details/125435628