拼写单词
题目描述
给你一份『词汇表』(字符串数组) words 和一张『字母表』(字符串) chars。
假如你可以用 chars 中的『字母』(字符)拼写出 words 中的某个『单词』(字符串),那么我们就认为你掌握了这个单词。
注意:每次拼写(指拼写词汇表中的一个单词)时,chars 中的每个字母都只能用一次。
返回词汇表 words 中你掌握的所有单词的 长度之和。
来源:力扣(LeetCode)1160
链接:https://leetcode-cn.com/problems/find-words-that-can-be-formed-by-characters
示例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。
思路题解
在这里选择最常规的解题思路,后续会补充其他方法。
本题简化后其实就是看词汇表中每个单词中的每个字符能否在字母表中找到。然后返回所有单词的长度之和。
题中给的词汇表可以看成是一个二维数组,字母表看成是一个一维数组,那么就需要三层for循环嵌套遍历。如果遍历到字母表中存在该字符,则退出当前循环。
那么我怎么记录这个单词中的所有字符都能在字母表中找到呢?我们可以设一个标志变量,初始为0,每当找到一个则标志位自增1,看最后标志变量是否等于该单词的长度。因为每个单词都需要一个标志变量,所以将其放在遍历每个单词后边并清0,即将 int flag = 0 放在第一个for循环之后。
还有一个问题,题中要求我们每个字符只能用一次,我们可以再设一个标志变量来记录看哪个单词是否被用过,但是这样比较麻烦,最省事的办法就是直接删掉。可如果直接删掉的话,下一个单词再去遍历字母表的时候,字母表原数据就被改变了,那么我们可以再拷贝一个字母表副本,删除的话对这个副本进行操作。
示例代码
class Solution {
public:
int countCharacters(vector<string>& words, string chars) {
int count =0;
for(int i = 0; i < words.size(); ++i) //遍历词汇表中每个单词
{
int flag = 0; //满足构成单词的字符个数
string copy = chars; //拷贝字母表,以便删除后能恢复
for(int j = 0; j < words[i].size(); ++j) //遍历词汇表中单词的每个字符
{
for(int k = 0; k < copy.size(); ++k) //遍历字母表的每个字符
{
if(words[i][j] == copy[k]) //如果在字母表中找到能构成单词的字符 则删除该字符 退出循环
{
copy.erase(copy.begin() + k);
flag++;
break;
}
}
}
if(flag == words[i].size()) //如果该单词在字母表中都能找到,且每个字符只用一次
count += flag;
}
return count;
}
};
写在最后
本人刷题小白一枚,记录一下自己刷题时的思路,方便以后回顾总结,如有问题,欢迎指出!
图片来源于网络