「携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第6天,点击查看活动详情」
今天我们来做一下今天的leetcode上一道中等题
题目链接在这里 面试题 17.13. 恢复空格
题意
这个题目说给我们一个句子和一些单词,找出这些句子中没有识别成完整单词的最少字符数。 比如:"jesslooked" 这个句子,单词列表是 ["looked"],其中未识别的字符最少就是jess,即4个了。
思路
涉及到字符串最值问题,很多时候都需要往动态规划这方面靠,比如这道题,就需要用到动态规划的思想。那么,如果使用动态规划考虑这道题目呢?拿题目的第一个示例来说的话
- 我们可以从最简单的情况开始考虑,如果原句子是一个空字符串,那么其中的最少未识别的字符数当然是0了
- 紧接着,我们可以考虑将第一个字符加进去,也就是j,因为现在有一个字符了,所以未识别的字符数可以先默认为1,然后,我们可能需要遍历单词列表,看有没有以j结尾的单词,因为有可能j是一个完整的单词。当然,结果是没有找到,这样我们就知道了前一个字符中未识别的字符数为1.
- 然后,前2个、3个、...9个字符都按照上述的方法进行考虑,都可以得出相应的最少值。
- 接下来,我们看前10个字符中未识别的字符数,默认是10,同样我们去单词列表中查看,这时我们发现looked在句子结尾命中了,也就意味着前10个字符中第5个字符到结尾是一个完整单词,所以前10个单词中未识别的字符数 就等于 前4个字符中未识别的字符数,所以最终得出4
- 考虑前11个字符hesslookedj时,由于我们已经知道了前10个字符中未识别的字符数最小为4,现在增加一个字符,所以前11个字符的对应的值默认为5,同样的,然后我们去单词列表中查找有没有以第11个字符结尾的单词,发现没有找到,所以最终得出5
- ...
- 根据上述考虑思路,我们最终可以得出整个字符串的最少未识别的字符数,你可能会写出如下代码
这份代码在leetcode的目前的数据范围是可以通过的 ,但是我们可以注意到其中的复杂度的大小为O(m*n) m为句子的长度,n是单词列表的长度,那么,如果m、n超过10000的话,复杂度就超标的
紧接着,我们可以思考,那里还可以进行优化呢? 我们会注意到在 迭代前i个字符串的最少未识别的字符数时,我们重复的从单词表中 去查找有没有以第i个字符结尾的单词。这一步我们其实可以运用到字典树(前缀树) 去初始化一些信息,也就是 句子中前i个字符中以第i个字符结尾的完整单词的前面的位置,有了这些信息,我们就可以根据i直接 从可以匹配成完整单词的列表中计算了,这会大大缩短计算的时间。
这样,我们就分析完了这道题目的解题思路。
代码实现
了解了上面的思路之后,代码实现其实就非常简单了😎。
结束语
如果有更好的分析思路,欢迎大家在评论区发表看法!⛄