题目
给你一份『词汇表』(字符串数组) words 和一张『字母表』(字符串) chars。
假如你可以用 chars 中的『字母』(字符)拼写出 words 中的某个『单词』(字符串),那么我们就认为你掌握了这个单词。
注意:每次拼写时,chars 中的每个字母都只能用一次。
返回词汇表 words 中你掌握的所有单词的 长度之和。
示例 1:
输入:words = ["cat","bt","hat","tree"], chars = "atach"
输出:6
解释:
可以形成字符串 "cat" 和 "hat",所以答案是 3 + 3 = 6。
示例 2:
输入:words = ["hello","world","leetcode"], chars = "welldonehoneyr"
输出:10
解释:
可以形成字符串 "hello" 和 "world",所以答案是 5 + 5 = 10。
提示:
1. 1 <= words.length <= 1000
2. 1 <= words[i].length, chars.length <= 100
3. 所有字符串中都仅包含小写英文字母
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/find-words-that-can-be-formed-by-characters
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
Go版本实现
执行用时:112 ms
内存消耗:6.5 MB
func countCharacters(words []string, chars string) int {
num := 0
chars_map := make(map[byte]int)
//get map of chars
charray := []byte(chars)
for _,ch := range charray {
chars_map[ch] = strings.Count(chars,string(ch))
}
for _,ww := range words {
mymap := make(map[byte]int)
//get ww map
wwarray := []byte(ww)
for _,i := range wwarray {
mymap[i] = strings.Count(ww,string(i))
}
flag := true
//compare ww and chars_map
for a,b := range mymap {
if chars_map[a] < b {
flag = false
break
}
}
if flag==true {
num += len(ww)
}
}
return num
}
我的第一版实现充分展示了什么叫简单的事情复杂做,又用上了字符串函数strings.Count,又需要一直将string转成[]byte,再将byte转成string。解题的思路还是正确的,其实是用哈希表存储字符串中的每个字母出现的次数,然后就是字母表和单词进行对比字母的次数。
经过学习后,我实现了下面这一版代码,巧用提示中字符串中仅有小写字母。所以就可以用[26]int来记录26个小写字母的出现次数。使用数组而不是map来记录。
执行用时:16 ms
内存消耗:6.2 MB
func countCharacters(words []string, chars string) int {
//using [26]int recording the count of bytes
var byteCount [26]int
num := 0
for _,char := range chars {
byteCount[char-'a']++
}
//check byte count of word according to chars
for _,word := range words {
//a copy of byteCount and a flag
bc,match := byteCount,true
for _,ww := range word {
if bc[ww-'a'] <= 0 {
match = false
break
}
bc[ww-'a']--
}
if match {
num += len(word)
}
}
return num
}
总结
巴菲特曾经说过,如果你在市场中待的足够久,你会遇到各种各样的事情。所以,我们也需要在leetcode和工作学习中待得足够久,就会踩坑无数,心中有数!