LeetCode 1472. Concatenated Words - 亚马逊高频题6

给定一个没有重复的字符串数组,找到所有可以由数组中较短单词组成的连接词。利用动态规划,先对单词按长度排序,然后从左到右检查每个单词是否能由前面的单词组成。通过判断单词中间部分是否为数组中的单词来确定连接可能性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Given an array of strings words (without duplicates), return all the concatenated words in the given list of words.

concatenated word is defined as a string that is comprised entirely of at least two shorter words in the given array.

Example 1:

Input: words = ["cat","cats","catsdogcats","dog","dogcatsdog","hippopotamuses","rat","ratcatdogcat"]
Output: ["catsdogcats","dogcatsdog","ratcatdogcat"]
Explanation: "catsdogcats" can be concatenated by "cats", "dog" and "cats"; 
"dogcatsdog" can be concatenated by "dog", "cats" and "dog"; 
"ratcatdogcat" can be concatenated by "rat", "cat", "dog" and "cat".

Example 2:

Input: words = ["cat","dog","catdog"]
Output: ["catdog"]

Constraints:

  • 1 <= words.length <= 104
  • 0 <= words[i].length <= 30
  • words[i] consists of only lowercase English letters.
  • 0 <= sum(words[i].length) <= 105

题目给定一个字符串数组words,数组中含有一系列长度不等的单词(无重复单词),要求找出所有可以由数组中更短的单词连接而成的单词。

一个单词肯定是由比它自身长度短的单词连接而成,显然对于数组words里单词,我们应该从短到长进行判断,因此首先应该对words里单词按长度进行排序,然后在从左到右判断依次当前单词是否可以由它前面的单词连接而成。

那么该如何判断一个单词是否能由一组更短的单词连接而成呢?这里可以使用动态规划来解,如果我们能知道单词的任意一个位置到单词开头部分是否由更短单词连接而成,那么单词最后一个位置到开头就是单词本身,从而也就知道该该单词能否由更短的单词连接而成。对于单词中的一个位置i,如果能找到它前面某个位置j之前是可连接单词,那么只要判断j和i之间构成的单词是否是数组words中的一个单词,如果是,那么从i到单词头构成的单词就是一个可连接词。由此可以看出,只要位置i之前的位置都判断过了,那么就可能快速判断第i位置。因此,我们可以按此方法从数组的第0位置到第n-1位置依次判断,判断完第n-1位置就可以知道答案。

class Solution:
    def findAllConcatenatedWordsInADict(self, words: List[str]) -> List[str]:
        def comp(w1, w2):
            return len(w1) - len(w2)
        words.sort(key=cmp_to_key(comp))
        self.wset = set()
        
        res =[]
        for w in words:
            if self.concatenated(w):
                res.append(w)
            self.wset.add(w)
        return res
    
    def concatenated(self, word: str)->bool:
        n = len(word)
        if n == 0:
            return False
        dp = [False] * (n + 1)
        dp[0] = True
        for i in range(1, n+1):
            for j in range(i - 1, -1, -1):
                if dp[j] and word[j:i] in self.wset:
                    dp[i] = True
                    break
        
        return dp[n]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值