Given a string and a string dictionary, find the longest string in the dictionary that can be formed by deleting some characters of the given string. If there are more than one possible results, return the longest word with the smallest lexicographical order. If there is no possible result, return the empty string.
Example 1:
Input: s = "abpcplea", d = ["ale","apple","monkey","plea"] Output: "apple"
Example 2:
Input: s = "abpcplea", d = ["a","b","c"] Output: "a"
Note:
- All the strings in the input will only contain lower-case letters.
- The size of the dictionary won‘t exceed 1,000.
- The length of all the strings in the input won‘t exceed 1,000.
这道题给了我们一个字符串,和一个字典,让我们找到字典中最长的一个单词,这个单词可以通过给定单词通过删除某些字符得到。由于只能删除某些字符,并不能重新排序,所以我们不能通过统计字符出现个数的方法来判断是否能得到该单词,而是只能老老实实的按顺序遍历每一个字符。我们可以给字典排序,通过重写comparator来实现按长度由大到小来排,如果长度相等的就按字母顺序来排。然后我们开始遍历每一个单词,用一个变量i来记录单词中的某个字母的位置,我们遍历给定字符串,如果遍历到单词中的某个字母来,i自增1,如果没有,就继续往下遍历。这样如果最后i和单词长度相等,说明单词中的所有字母都按顺序出现在了字符串s中,由于字典中的单词已经按要求排过序了,所以第一个通过验证的单词一定是正确答案,我们直接返回当前单词即可,参见代码如下:
解法一:
class Solution { public: string findLongestWord(string s, vector<string>& d) { sort(d.begin(), d.end(), [](string a, string b){ if (a.size() == b.size()) return a < b; return a.size() > b.size(); }); for (string str : d) { int i = 0; for (char c : s) { if (i < str.size() && c == str[i]) ++i; } if (i == str.size()) return str; } return ""; } };
上面的方法中用到了sort排序,会占用大量时间,如果我们想进一步优化,就可以不用排序。我们遍历字典中的单词,然后还是跟上面的方法一样来验证当前单词是否能由字符串s通过删除字符来得到,如果能得到,而且单词长度大于等于结果res的长度,我们再看是否需要更新结果res,有两种情况是必须要更新结果res的,一个是当前单词长度大于结果res的长度,另一种是当前单词长度和res相同,但是字母顺序小于结果res,这两种情况下更新结果res即可,参见代码如下:
解法二:
class Solution { public: string findLongestWord(string s, vector<string>& d) { string res = ""; for (string str : d) { int i = 0; for (char c : s) { if (i < str.size() && c == str[i]) ++i; } if (i == str.size() && str.size() >= res.size()) { if (str.size() > res.size() || str < res) { res = str; } } } return res; } };
参考资料:
https://discuss.leetcode.com/topic/80876/10-lines-solutions-for-c
LeetCode All in One 题目讲解汇总(持续更新中...)