题目地址:
https://leetcode.com/problems/longest-word-in-dictionary-through-deleting/
给定一个字符串 s s s,再给定一个字符串组成的数组 A A A,求所有 A A A中是 s s s的子序列的字符串中最长的那个。若答案不唯一,则返回字典序最小的。若答案不存在,则返回空串。
思路是用堆,遍历数组,然后先判断当前字符串 a a a是否是 s s s的子序列,如果不是直接略过,如果是,则视堆的情况而定:如果堆空,或者字符串 a a a的长度等于堆顶字符串的长度,则直接入堆;否则的话,如果 a a a的长度大于堆顶字符串长度,则将堆清空后将 a a a入堆(因为我们要返回最长的那个),如果 a a a的长度小于堆顶字符串长度则直接略过。代码如下:
import java.util.ArrayList;
import java.util.List;
import java.util.PriorityQueue;
public class Solution {
public String findLongestWord(String s, List<String> d) {
PriorityQueue<String> pq = new PriorityQueue<>();
for (String sub : d) {
if (isSubsequence(s, sub)) {
if (!pq.isEmpty() && pq.peek().length() < sub.length()) {
pq.clear();
pq.offer(sub);
} else if (pq.isEmpty() || pq.peek().length() == sub.length()) {
pq.offer(sub);
}
}
}
// 答案不存在的话要返回空串,所以这里还需要判断一下
return pq.isEmpty() ? "" : pq.peek();
}
// 判断sub是否是s的子序列
private boolean isSubsequence(String s, String sub) {
int j = 0;
for (int i = 0; i < s.length() && j < sub.length(); i++) {
if (s.charAt(i) == sub.charAt(j)) {
j++;
}
}
return j == sub.length();
}
}
时间复杂度 O ( l 2 n log n ) O(l^2n\log n) O(l2nlogn)(判断子序列需要 O ( l ) O(l) O(l),入堆最差需要 O ( l n log n ) O(ln\log n) O(lnlogn),虽说看起来时间复杂度很高,但由于堆可能经常清空,所以真实耗时未必有这么高),空间 O ( n l ) O(nl) O(nl)。