#LeetCode1160.拼写单词(每日一题)
给你一份【词汇表】(字符串数组)words和一张【字母表】(字符串)chars。
假如你可以用chars中的【字母】(字符)拼写出words中的某个【单词】(字符串),那么就认为掌握了这个单词。
注意:每次拼写时,chars中的每个字母都只能用一次。
返回词汇表words中你掌握的所有单词的长度之和。
其实这道题在LeetCode上标记为简单题,看到题目自然想到用HashMap来做:
- 用两个HashMap,一个charMap用来存储chars中的【字母】(字符)及其个数,另一个stringMap用来存储【词汇表】(字符串数组)words中的【字母】(字符)及其个数;
- 将两个HashMap中相对应的键值进行比较,只要stringMap中相对应的键值小于等于charMap中相对应的键值,长度加上该单词的长度;
- 用到的Map的遍历是很方便很喜欢的:for(Map.Entry<Character,Integer> e:stringMap.entrySet())
public int countCharacters(String[] words, String chars) {
if(words.length==0)return 0;
int length=0;
Map<Character,Integer> stringMap=new HashMap<Character,Integer>();
Map<Character,Integer> charMap=new HashMap<Character,Integer>();
for(int i=0;i<chars.length();++i){
if(!charMap.containsKey(chars.charAt(i)))
charMap.put(chars.charAt(i),1);
else
charMap.put(chars.charAt(i),charMap.get(chars.charAt(i))+1);
}
for(int i=0;i<words.length;++i){
String currWord=words[i];
boolean b=true;
for(int j=0;j<currWord.length();++j){
if(!stringMap.containsKey(currWord.charAt(j)))
stringMap.put(currWord.charAt(j),1);
else{
stringMap.put(currWord.charAt(j),stringMap.get(currWord.charAt(j))+1);
}
}
//在这里用到的是一种遍历Map的超好用的方法(特别是容量较大时!):
//Map中采用Entry内部类来表示一个映射项,映射项包含Key和Value , 每一对键值就是一个Entry,包含getKey()和getValue()方法
//entrySet是 java中 键值对的集合,实现了Set接口,Set里面的类型是Map.Entry,可以通过map.entrySet()得到
for(Map.Entry<Character,Integer> e:stringMap.entrySet()){
if(charMap.containsKey(e.getKey())&&e.getValue()<=charMap.get(e.getKey()))
b=true;
else{
b=false;
break;
}
}
if(b)length=length+currWord.length();
stringMap.clear();
}
return length;
}
以上方法时间复杂度O(N);
后来看题解时,看到基于ASCII码的26个字母组成的数组的方法(a的ASCII值为97,A的ASCII值为65),思路很巧妙:
public int countCharacters(String[] words, String chars) {
int length=0;
int[] charLetters=new int[26];
//遍历chars,统计出现的字母及其个数
for(char c:chars.toCharArray()){
//用字母之间的ASCII值做差的数字来作为下标,int[0]=1就代表字母a出现了一次,真的很巧妙了,学到了
charLetters[c-'a']+=1;
}
//遍历words,统计words中每一个单词中出现的字母及其个数
//JAVA中的循环体的标签真的很好用,可以直接在内层循环中跳到外层循环的下一次操作,就像一个开关,随时开启循环。
a:for(String word:words){
int[] wordLetters=new int[26];
for(char w:word.toCharArray()){
wordLetters[w-'a']+=1;
}
for(int i=0;i<26;++i){
if(wordLetters[i]>charLetters[i])
continue a;
}
length+=word.length();
}
return length;
}
虽然是简单题,但是寻找更优解的过程中也学到了很多。