问题描述:
给定一个车牌号,找出words里面包含所有车牌号字母且最短的单词
思路:
(1)题目中提到不区分大小写,但车牌号里大小写均有,所以我们先转化成小写
(2)找出车牌号里面所有字母,并记录在一个list里面
(3)写一个function,判断某一个单词是否包含列表里面所有的字母
3.1 用hashmap记录list里面所有的字母及其出现次数(可以一开始就用map)
3.2 遍历这个字符串,如果当下字符是列表字符,则其对应数量-1
3.3 再次遍历hashmap,判断每个key对应的value是否都小于零,若都小于零,则证明字符串包含所有的列表里的字母
(4) 若(3)返回true,则将该字符串加入到候选人列表里
(5)遍历候选人列表,找出最佳候选人(第一个长度最短的)
代码如下:
class Solution {
public String shortestCompletingWord(String licensePlate, String[] words) {
//step1: find all letter in the LP
String newStr=licensePlate.toLowerCase();
List<Character> list=new ArrayList<>();
List<String> candidate=new ArrayList<>();
for(int i=0; i<newStr.length(); i++){
if (newStr.charAt(i)>='a'){
list.add(newStr.charAt(i));
}
}
int numOfLetter=list.size();
//step2: scan through the words
for(String s: words){
//if s contains all letters in the list, then add it to the candiate list
if(containsAll(s,list)){//at least complete
candidate.add(s);
}
}
//step3: search the candidate list
int min=16;
int currentBest=0;
for(int i=0; i<candidate.size(); i++){
if(candidate.get(i).length()<min){
min=candidate.get(i).length();
currentBest=i;
}
}
return candidate.get(currentBest);
}
private boolean containsAll(String s, List<Character> list){
Map<Character, Integer> map =new HashMap<>();
for(Character c: list){
map.put(c, map.getOrDefault(c,0)+1);
}
for(int i=0; i<s.length(); i++){
if(map.containsKey(s.charAt(i))){
map.replace(s.charAt(i), map.get(s.charAt(i))-1);
}
}
for(Character c: map.keySet()){
if(map.get(c)>0) return false;
}
return true;
}
}
时间复杂度: 由于车牌号只有7位,所以list中字母不会超过7。 又因为每个单词最多15位,所以每次containsALL判断可以近似认为是常数时间O(1)。所以最终的时间复杂度相当于遍历words的,即O(n), n是words数组长度