给出一个单词数组 words ,其中每个单词都由小写英文字母组成。
如果我们可以 不改变其他字符的顺序 ,在 wordA 的任何地方添加 恰好一个 字母使其变成 wordB ,那么我们认为 wordA 是 wordB 的 前身 。
例如,“abc” 是 “abac” 的 前身 ,而 “cba” 不是 “bcad” 的 前身
词链是单词 [word_1, word_2, …, word_k] 组成的序列,k >= 1,其中 word1 是 word2 的前身,word2 是 word3 的前身,依此类推。一个单词通常是 k == 1 的 单词链 。
从给定单词列表 words 中选择单词组成词链,返回 词链的 最长可能长度 。
示例 1:
输入:words = [“a”,“b”,“ba”,“bca”,“bda”,“bdca”]
输出:4
解释:最长单词链之一为 [“a”,“ba”,“bda”,“bdca”]
示例 2:
输入:words = [“xbc”,“pcxbcf”,“xb”,“cxbc”,“pcxbc”]
输出:5
解释:所有的单词都可以放入单词链 [“xb”, “xbc”, “cxbc”, “pcxbc”, “pcxbcf”].
示例 3:
输入:words = [“abcd”,“dbqca”]
输出:1
解释:字链[“abcd”]是最长的字链之一。
[“abcd”,“dbqca”]不是一个有效的单词链,因为字母的顺序被改变了。
提示:
1 <= words.length <= 1000
1 <= words[i].length <= 16
words[i] 仅由小写英文字母组成。
前置了解:
python中defaultdict用法详解
一般是dict={},添加元素的只需要dict[element] =value即,调用的时候也是如此,dict[element] = xxx,但前提是element字典里,如果不在字典里就会报错,这时defaultdict就能排上用场了,defaultdict的作用是在于,当字典里的key不存在但被查找时,返回的不是keyError而是一个默认值,比如list对应[ ],str对应的是空字符串,set对应set( ),int对应0
List
具体的语法是可以归纳为两点:
在声明变量时,变量的后面可以加一个冒号,后面再写上变量的类型,如 int、list 等等。
在声明方法返回值的时候,可以在方法的后面加一个箭头,后面加上返回值的类型,如 int、list 等等。
如
def add(a: int) -> int:
return a + 1
申明它返回一个int类型,但值得注意的是,这种类型和变量注解实际上只是一种类型提示,对运行实际上是没有影响的,比如调用 add 方法的时候,我们传入的不是 int 类型,而是一个 float 类型,它也不会报错,也不会对参数进行类型转换,不过有了类型注解,一些 IDE 是可以识别出来并提示的,比如 PyCharm 就可以识别出来在调用某个方法的时候参数类型不一致,会提示 WARNING。
values()返还{keys:value}的value
list(values)即返还[value1,value2,…]
sort(key=len)按照字符串链长度排序自短至长
解题思路:
1.首先对无序的单词集合进行由短至长排序
2.定义字典dp,key代表每个单词word,value代表以该单词结尾的链的最大长度(初始为0)
3.遍历words,去掉单独字符后的word_strip如果在单词列表中出现,结尾的链增加一个长度(与dp[word]比较选更大的),如果word去掉每个位置处的字母得到的新单词都没有出现在单词列表words中,则dp[word]设置为1。
代码:
from typing import List
from collections import defaultdict
class Solution:
def longestStrChain(self, words: List[str]) -> int:
dp = defaultdict(int)
words.sort(key=len)
for word in words:
for i in range(len(word)):
word_strip = word[:i] + word[i + 1:]
dp[word] = max(dp[word], dp[word_strip] + 1)
return max(dp.values())