Medium
题目描述
给你一个字符串 s 和一个字符串数组 dictionary ,找出并返回 dictionary 中最长的字符串,该字符串可以通过删除 s 中的某些字符得到。
如果答案不止一个,返回长度最长且字典序最小的字符串。如果答案不存在,则返回空字符串。
示例 1:
输入:s = "abpcplea", dictionary = ["ale","apple","monkey","plea"]
输出:"apple"
示例 2:
输入:s = "abpcplea", dictionary = ["a","b","c"]
输出:"a"
提示:
1 <= s.length <= 10001 <= dictionary.length <= 10001 <= dictionary[i].length <= 1000s和dictionary[i]仅由小写英文字母组成
解题思路
这是一道典型的子序列匹配问题,核心是判断字典中的每个单词是否是字符串 s 的子序列。
解题思路:
子序列判断:使用双指针技术判断一个字符串是否是另一个字符串的子序列。对于字典中的每个单词,用一个指针遍历该单词,另一个指针遍历字符串
s,当字符匹配时两个指针都前进,否则只有s的指针前进。结果选择:在所有能匹配的单词中,选择长度最长的。如果长度相同,选择字典序最小的。
优化策略:
- 方法一:先按长度降序、字典序升序排序,找到第一个匹配的单词即为答案
- 方法二:遍历所有单词,维护当前最优答案
推荐解法: 使用排序优化的方法,可以在找到第一个匹配的单词时立即返回,避免不必要的比较。
时间复杂度主要由排序和子序列匹配两部分组成,空间复杂度为常数级别。
代码实现
class Solution {
public:
string findLongestWord(string s, vector<string>& dictionary) {
// 按长度降序,字典序升序排序
sort(dictionary.begin(), dictionary.end(), [](const string& a, const string& b) {
return a.length() != b.length() ? a.length() > b.length() : a < b;
});
// 检查第一个匹配的单词
for (const string& word : dictionary) {
if (isSubsequence(word, s)) {
return word;
}
}
return "";
}
private:
bool isSubsequence(const string& word, const string& s) {
int i = 0, j = 0;
while (i < word.length() && j < s.length()) {
if (word[i] == s[j]) {
i++;
}
j++;
}
return i == word.length();
}
};
class Solution:
def findLongestWord(self, s: str, dictionary: List[str]) -> str:
# 按长度降序,字典序升序排序
dictionary.sort(key=lambda x: (-len(x), x))
# 检查第一个匹配的单词
for word in dictionary:
if self.isSubsequence(word, s):
return word
return ""
def isSubsequence(self, word: str, s: str) -> bool:
i = j = 0
while i < len(word) and j < len(s):
if word[i] == s[j]:
i += 1
j += 1
return i == len(word)
public class Solution {
public string FindLongestWord(string s, IList<string> dictionary) {
// 按长度降序,字典序升序排序
var sortedDict = dictionary.OrderByDescending(w => w.Length)
.ThenBy(w => w)
.ToList();
// 检查第一个匹配的单词
foreach (string word in sortedDict) {
if (IsSubsequence(word, s)) {
return word;
}
}
return "";
}
private bool IsSubsequence(string word, string s) {
int i = 0, j = 0;
while (i < word.Length && j < s.Length) {
if (word[i] == s[j]) {
i++;
}
j++;
}
return i == word.Length;
}
}
var findLongestWord = function(s, dictionary) {
function isSubsequence(word, str) {
let i = 0, j = 0;
while (i < word.length && j < str.length) {
if (word[i] === str[j]) {
i++;
}
j++;
}
return i === word.length;
}
let result = "";
for (let word of dictionary) {
if (isSubsequence(word, s)) {
if (word.length > result.length ||
(word.length === result.length && word < result)) {
result = word;
}
}
}
return result;
};
复杂度分析
| 复杂度 | 大小 |
|---|---|
| 时间复杂度 | O(n log n + n × m),其中 n 是字典长度,m 是字符串平均长度 |
| 空间复杂度 | O(1),不考虑排序的额外空间 |
相关题目
- . Longest Word in Dictionary (Medium)