LeetCode-472 连接词

本文涉及的产品
智能开放搜索 OpenSearch行业算法版,1GB 20LCU 1个月
实时数仓Hologres,5000CU*H 100GB 3个月
实时计算 Flink 版,5000CU*H 3个月
简介: LeetCode-472 连接词

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/concatenated-words

题目描述

给你一个 不含重复 单词的字符串数组 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" 组成。
示例 2:
输入:words = ["cat","dog","catdog"]
输出:["catdog"]
提示:
1 <= words.length <= 104
0 <= words[i].length <= 1000
words[i] 仅由小写字母组成
0 <= sum(words[i].length) <= 105

解题思路

这道题还是挺复杂的,啃了一天才做出来。

首先要了解什么是字典树,字典树就是一棵前缀树,相同前缀的字符串会位于同一棵字典树的不同分支,本题主要思路就是先将所有单词按照单词长度升序排序。然后依次遍历单词,使用dfs的方法判断 单词是否是由字典树上的单词构成的,若是,则是连接词,如果不是,则将这个单词加入连接词。

字典树是一颗多叉树,这里没有用传统的多叉树的存储形式,而是在每个结点中使用了vector记录所有子树结点构成了一颗多叉树。结点中使用char来记录连接到这个结点的边,边的值就是字母。并且用一个标志位记录当前词在words中位置。

添加字典树结点的部分过程是从顶到底遍历字典树,并且遍历单词中每个字母,判断是否可以找到相同的路径使得路径上的字母和单词相同,如果没有就在分歧点新增入结点。

dfs过程则是利用深度优先找是否路径使得路径上的字母和单词相同的过程。

代码展示

 

class Solution {
public:
    class DictionaryTree
    {
    public:
        char mcEdge;
        int miEnd = -1;
        vector<DictionaryTree*> mvzChildren;
    };
    int AddDictionaryTreeNode(DictionaryTree* vzDictionaryTree, string s, int index)
    {
        DictionaryTree* p = vzDictionaryTree;
        for(auto c:s)
        {
            bool bFinded = false;
            for(int i = 0; i < p->mvzChildren.size(); i++)
            {
                if(p->mvzChildren[i]->mcEdge == c)
                {
                    p = p->mvzChildren[i];
                    bFinded = true;
                    break;
                }
            }
            if(!bFinded)
            {
                DictionaryTree* q = new DictionaryTree;
                q->mcEdge = c;
                p->mvzChildren.push_back(q);
                p = q;
            }
        }
        p->miEnd = index;
        return 0;
    }
    bool dfs(DictionaryTree* vzDictionaryTree, string s, int start)
    {
        if (s.length() == start) {
            return true;
        }
        DictionaryTree* p = vzDictionaryTree;
        for (int i = start; i < s.length(); i++) {
            char ch = s[i];
            bool bFind = false;
            int iIndex = 0;
            for(; iIndex < p->mvzChildren.size(); iIndex++)
            {
                if(p->mvzChildren[iIndex]->mcEdge == ch)
                {
                    bFind = true;
                    break;
                }
            }
            if (!bFind) {
                return false;
            }
            p = p->mvzChildren[iIndex];
            if (p->miEnd != -1) {
                if (dfs(vzDictionaryTree, s, i + 1)) 
                {
                    return true;
                }
            }
        }
        return false;
    }
    vector<string> findAllConcatenatedWordsInADict(vector<string>& words) {
        vector<string> vstrRet;
        sort(words.begin(), words.end(), [](string a, string b) -> bool { return a.size() < b.size();});
        DictionaryTree zDictionaryTree;
        for(int is = 0; is < words.size(); is++)
        {
            if(words[is].size() == 0)
                continue;
            if(dfs(&zDictionaryTree, words[is], 0))
            {
                vstrRet.push_back(words[is]);
            }
            else
            {
                AddDictionaryTreeNode(&zDictionaryTree, words[is], is);
            }
        }
        return vstrRet;
    }
};

运行结果

 

相关文章
|
6月前
LeetCode
LeetCode
39 0
|
6月前
leetcode-827:最大人工岛
leetcode-827:最大人工岛
62 0
|
存储
leetcode:53.最大字序和
给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
53 0
|
索引
LeetCode 354. Russian Doll Envelopes
给定一些标记了宽度和高度的信封,宽度和高度以整数对形式 (w, h) 出现。当另一个信封的宽度和高度都比这个信封大的时候,这个信封就可以放进另一个信封里,如同俄罗斯套娃一样。 请计算最多能有多少个信封能组成一组“俄罗斯套娃”信封(即可以把一个信封放到另一个信封里面)。
81 0
LeetCode 354. Russian Doll Envelopes
|
算法 Python
LeetCode 386. Lexicographical Numbers
给定一个整数 n, 返回从 1 到 n 的字典顺序。
84 0
LeetCode 386. Lexicographical Numbers
|
存储
leetcode第52题
可以发现对于同一条副对角线,row + col 的值是相等的。 对于同一条主对角线,row - col 的值是相等的。 我们同样可以用一个 bool 型数组,来保存当前对角线是否有元素,把它们相加相减的值作为下标。 对于 row - col ,由于出现了负数,所以可以加 1 个 n,由 [ - 3, 3 ] 转换为 [ 1 , 7 ] 。
leetcode第52题
|
存储 算法
leetcode第43题
个位乘个位,得出一个数,然后个位乘十位,全部乘完以后,就再用十位乘以各个位。然后百位乘以各个位,最后将每次得出的数相加。十位的结果要补 1 个 0 ,百位的结果要补两个 0 。相加的话我们可以直接用之前的大数相加。直接看代码吧。
leetcode第43题
|
算法
leetcode第34题
第二种思路,参考这里。 我们开始更新 start 的时候,是 mid + 1,如果剩两个元素,例如 2 4,target = 6 的话,此时 mid = 0,start = mid + 1 = 1,我们返回 start + 1 = 2。如果 mid 是右端点,那么 mid = 1,start = mid + 1 = 2,这样就可以直接返回 start 了,不需要在返回的时候加 1 了。
104 0
leetcode第34题