LeetCode 524. 通过删除字母匹配到字典里最长单词
题目描述

题意分析
删除字符会保留剩余字符的相对顺序,因此要从字典中找出属于
s的子序列的单词。答案先按长度取最大值,长度相同时再取字典序最小值;没有任何匹配时返回空串。
解法:枚举词典并双指针匹配
核心思路
[!blue]
对每个候选单词单独判断子序列关系。用
i指向候选中下一个待匹配字符,用j从左到右扫描源串:字符相等就推进i,无论是否相等都推进j。因此已经匹配的字符顺序不变,源串中未匹配的字符对应删除操作。总是使用最早可用的相同字符不会漏解。假设某个合法匹配使用了更靠后的位置,把这一次匹配换到较早位置后,后续原有的匹配位置仍然有效。逐个字符这样处理,就为剩余字符保留了最多空间。
当
i到达候选末尾,说明全部字符已经按顺序匹配,候选有效;若源串扫描完仍有候选字符未匹配,则无效。对所有有效候选维护answer:更长时替换,等长且字典序更小时替换。这样每轮后answer都是已经检查过的单词中的最优解。
解题步骤
- 将答案初始化为空串,逐个检查字典单词。
- 每个单词都重新将两个游标归零,按字符是否相等推进候选游标,源串游标每轮都前进。
- 用候选是否全部匹配判断成功;成功时源串可以还有剩余字符。
- 仅对成功的候选比较长度和字典序,更新答案。
- 遍历完字典后返回答案;始终没有匹配时保留初始空串。
代码实现
class Solution {
// 最长优先、同长字典序最小优先是两层判断规则,答案更新可以边扫边比较。
public String findLongestWord(String s, List<String> dictionary) {
String answer = "";
for (String word : dictionary) {
if (!isSubsequence(word, s)) {
continue;
}
// 先比较长度,仅同长度时才比较字典序
if (word.length() > answer.length()
|| (word.length() == answer.length() && word.compareTo(answer) < 0)) {
answer = word;
}
}
return answer;
}
private boolean isSubsequence(String a, String b) {
int i = 0;
int j = 0;
while (i < a.length() && j < b.length()) {
// 只在匹配时推进候选,尽早匹配为后缀留下空间
if (a.charAt(i) == b.charAt(j)) {
i++;
}
j++;
}
return i == a.length();
}
}
func findLongestWord(s string, dictionary []string) string {
// 最长优先、同长字典序最小优先是两层判断规则,答案更新可以边扫边比较。
answer := ""
for _, w := range dictionary {
if !isSubseq564(w, s) {
continue
}
// 先比较长度,仅同长度时才比较字典序
if len(w) > len(answer) || (len(w) == len(answer) && w < answer) {
answer = w
}
}
return answer
}
func isSubseq564(a, b string) bool {
i, j := 0, 0
for i < len(a) && j < len(b) {
// 只在匹配时推进候选,尽早匹配为后缀留下空间
if a[i] == b[j] {
i++
}
j++
}
return i == len(a)
}
复杂度分析
- 时间复杂度:$O(D\lvert s\rvert)$,其中 $D$ 为字典词数。每个候选最多扫描源串一次;有效候选长度不超过 $\lvert s\rvert$,等长时的字典序比较也不超过这个量级。
- 空间复杂度:$O(1)$,答案引用已有单词,匹配只用两个游标。
关键点总结
[!green]
- 不能匹配的源字符可以删除,但不能跳过候选所需字符。
- 长度优先,字典序只用于同长比较。
易错点总结
[!yellow]
- 只比较长度,会让等长结果取决于字典输入顺序。
- 用源串是否扫描完判断成功,会拒绝提前完成的合法候选。
- 直接把字典首词设为答案,可能在无解时返回不合法单词。
相似题目
| 题目 | 难度 | 关联与区别 |
|---|---|---|
| 392. 判断子序列 | 简单 | 检查每个候选词是否为源串子序列是基础,本题再按长度和字典序选择最优候选。 |
| 792. 匹配子序列的单词数 | 中等 | 同样让多个词匹配一个长串,原题统计匹配数量,本题返回最长且字典序最小者。 |
转载与许可
许可
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处!