一、原题
描述: 给你一份『词汇表』(字符串数组) words 和一张『字母表』(字符串) chars。假如你可以用 chars 中的『字母』(字符)拼写出 words 中的某个『单词』(字符串),那么我们就认为你掌握了这个单词。
注意:每次拼写(指拼写词汇表中的一个单词)时,chars 中的每个字母都只能用一次。返回词汇表 words 中你掌握的所有单词的 长度之和
来源:力扣(LeetCode)
二、思路
1、个人思路
题目的意思就是对于words中的每个单词而言,若这个单词中出现的各个字符的数量不多于给定字符串chars中同一字符的数量,则我们“掌握”了这个单词。以示例1进行进一步解释:
字符串chars中各个字符的数量依次为——'a':2,'c':1, 't':1, 'h':1;words中的第一个单词cat中'c'出现了1次,'a'出现1次,t出现1次,因为1<1,1<2, 1<1,则“掌握”单词
单词bt中b出现1次,t出现1次,但是1 > 0 (即chars中没有字符b),因此我们没有掌握这一单词。
基于以上分析,我们只需要统计出chars中各个字符的数量,再统计出words的每一单词中字符的数量,进行比较即可。由于对python中的方法不甚熟悉,所以写的代码比较繁琐。
class Solution(object):
def countCharacters(self, words, chars):
"""
:type words: List[str]
:type chars: str
:rtype: int
"""
length = 0
nums = [0] * 26 # nums用于统计chars中各字符出现的次数,因为英文中一共26个字符,因此,nums的长度为26
for val in chars:
nums[ord(val) - ord('a')] += 1
for word in words:
num = [0] * 26
for char in word:
num[ord(char) - ord('a')] += 1
flag = 1 # flag用于判断当前循环的单词word是否可以被字符串chars中的字符组成,可以则为1
for i in range(26):
if num[i] > nums[i]: # 若词汇表中一单词中的字符出现次数大于该字符在nums中出现的次数,说明nums中的字符无法组成该单词
flag = 0
break;
if flag == 1:
length += len(word) # word可以被chars中的字符组成,则length加上该单词的长度
return length
2、官方解法
这里首先先介绍一下python中for-else结构,执行一下代码:
for i in range(5):
if i == 3:
print(i)
else:
print('else')
print('~~~~~')
for i in range(5):
if i == 3:
print(i)
break
else:
print('else')
可以看到,输出为:
3
else
~~~~
3
由输出可以看到:若for循环正常运行结束,则会执行其后的else语句;反之,若for循环异常结束(如循环体内执行了break语句),则不会执行其后的else语句。
了解了for-else结构,我们有以下代码:
class Solution:
def countCharacters(self, words: List[str], chars: str) -> int:
length = 0
nums = collections.Counter(chars)
for word in words:
word_num = collections.Counter(word)
for c in word_num:
if word_num[c] > nums[c]:
break;
else:
length += len(word)
return length