class Solution:
def findLongestWord(self, s: str, dictionary: List[str]) -> str:
def is_subsequence(word, s):
it = iter(s)
return all(char in it for char in word)
result = ""
for word in dictionary:
if is_subsequence(word, s):
if len(word) > len(result) or (len(word) == len(result) and word < result):
result = word
return result
class Solution {
public:
bool isSubsequence(const string& word, const string& s) {
int i = 0, j = 0;
while (i < word.size() && j < s.size()) {
if (word[i] == s[j]) i++;
j++;
}
return i == word.size();
}
string findLongestWord(string s, vector<string>& dictionary) {
string result = "";
for (const string& word : dictionary) {
if (isSubsequence(word, s)) {
if (word.size() > result.size() ||
(word.size() == result.size() && word < result)) {
result = word;
}
}
}
return result;
}
};
class Solution {
public String findLongestWord(String s, List<String> dictionary) {
String result = "";
for (String word : dictionary) {
if (isSubsequence(word, s)) {
if (word.length() > result.length() ||
(word.length() == result.length() && word.compareTo(result) < 0)) {
result = word;
}
}
}
return result;
}
private boolean isSubsequence(String word, String s) {
int i = 0, j = 0;
while (i < word.length() && j < s.length()) {
if (word.charAt(i) == s.charAt(j)) i++;
j++;
}
return i == word.length();
}
}
var findLongestWord = function(s, dictionary) {
function isSubsequence(word, s) {
let i = 0, j = 0;
while (i < word.length && j < s.length) {
if (word[i] === s[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;
};
Given a string s
and a list of strings dictionary
, find the longest string in dictionary
that can be formed by deleting some characters of s
without reordering the remaining characters. If there are multiple possible results, return the one that is lexicographically smallest. If there is no possible result, return an empty string.
s
– only delete.dictionary
can be used at most once.
At first glance, this problem seems to require checking, for every word in dictionary
, whether it can be formed by deleting characters from s
. The naive approach would be to try every possible combination of deletions, but that's extremely inefficient.
Instead, we can notice that the problem reduces to checking whether a word is a subsequence of s
. If it is, then we can form that word by deleting the appropriate characters from s
. So, for each word in the dictionary, we check if it's a subsequence of s
. If it is, we compare its length and lexicographic order to track the best candidate.
The brute-force solution would check every possible way to delete characters, but with the subsequence insight, we can check each word efficiently in linear time relative to the length of s
.
dictionary
, check if it is a subsequence of s
:
s
.s
whenever there is a character match.
This approach is efficient because checking if a word is a subsequence can be done in O(N) time, where N is the length of s
. By iterating through the dictionary once, we ensure we consider all candidates.
Consider s = "abpcplea"
and dictionary = ["ale","apple","monkey","plea"]
.
s
. Not a subsequence.The answer is "apple".
s
.dictionary
(let's say D words, each of length up to L), we check if it's a subsequence of s
(length N).
This problem is elegantly solved by recognizing that forming a word from s
via deletions is the same as checking if it is a subsequence. By iterating through the dictionary and checking each word with a two-pointer technique, we efficiently find the longest, lexicographically smallest valid word. This approach leverages simple string traversal and comparison, making it both readable and performant.