LeetCode-472 连接词

本文涉及的产品
实时计算 Flink 版,5000CU*H 3个月
检索分析服务 Elasticsearch 版,2核4GB开发者规格 1个月
大数据开发治理平台 DataWorks,不限时长
简介: 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;
    }
};

运行结果

 

相关文章
|
3月前
leetcode-1447:最简分数
leetcode-1447:最简分数
33 0
|
3月前
leetcode-1219:黄金矿工
leetcode-1219:黄金矿工
35 0
|
10月前
单链表反转 LeetCode 206
单链表反转 LeetCode 206
53 0
leetcode 827 最大人工岛
leetcode 827 最大人工岛
45 0
leetcode 827 最大人工岛
LeetCode 283. 移动零
给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。
67 0
|
存储 Python
LeetCode 66. Plus One
给定表示非负整数的非空数字数组,加上整数的1。 存储数字使得最高有效数字位于列表的开头,并且数组中的每个元素包含单个数字。 您可以假设整数不包含任何前导零,除了数字0本身。
67 0
LeetCode 66. Plus One
LeetCode 354. Russian Doll Envelopes
给定一些标记了宽度和高度的信封,宽度和高度以整数对形式 (w, h) 出现。当另一个信封的宽度和高度都比这个信封大的时候,这个信封就可以放进另一个信封里,如同俄罗斯套娃一样。 请计算最多能有多少个信封能组成一组“俄罗斯套娃”信封(即可以把一个信封放到另一个信封里面)。
63 0
LeetCode 354. Russian Doll Envelopes
|
存储 算法 索引
LeetCode 27+LeetCode 35 讲解(姊妹篇)
LeetCode 27+LeetCode 35 讲解(姊妹篇)
68 0
leetcode第55题
当自己按照 45 题的思路写完的时候,看 Solution 的时候都懵逼了,这道题竟然这么复杂?不过 Solution 把问题抽象成动态规划的思想,以及优化的过程还是非常值得学习的。
leetcode第55题
leetcode第51题
较经典的回溯问题了,我们需要做的就是先在第一行放一个皇后,然后进入回溯,放下一行皇后的位置,一直走下去,如果已经放的皇后的数目等于 n 了,就加到最后的结果中。然后再回到上一行,变化皇后的位置,然后去找其他的解。 期间如果遇到当前行所有的位置都不能放皇后了,就再回到上一行,然后变化皇后的位置。再返回到下一行。 说起来可能还费力些,直接看代码吧。
leetcode第51题

热门文章

最新文章