PAT-乙级 1039
写在前面:帮小红买东西吧 ( ̄▽ ̄) 今天加上思路upup!
小红想买些珠子做一串自己喜欢的珠串。卖珠子的摊主有很多串五颜六色的珠串,但是不肯把任何一串拆散了卖。于是小红要你帮忙判断一下,某串珠子里是否包含了全部自己想要的珠子?如果是,那么告诉她有多少多余的珠子;如果不是,那么告诉她缺了多少珠子。
为方便起见,我们用[0-9]、[a-z]、[A-Z]范围内的字符来表示颜色。例如在图1中,第3串是小红想做的珠串;那么第1串可以买,因为包含了全部她想要的珠子,还多了8颗不需要的珠子;第2串不能买,因为没有黑色珠子,并且少了一颗红色的珠子。
图 1
输入格式:
每个输入包含 1 个测试用例。每个测试用例分别在 2 行中先后给出摊主的珠串和小红想做的珠串,两串都不超过 1000 个珠子。
输出格式:
如果可以买,则在一行中输出 Yes
以及有多少多余的珠子;如果不可以买,则在一行中输出 No
以及缺了多少珠子。其间以 1 个空格分隔。
输入样例 1:
ppRYYGrrYBR2258
YrR8RrY
输出样例 1:
Yes 8
输入样例 2:
ppRYYGrrYB225
YrR8RrY
输出样例 2:
No 2
总体思路:
- 只要小红想要的其中一个比摊主给的多,那就是不够,即No。只有她想要的都可以被满足才能是Yes。
- Yes时,多的个数是两个 String 字符串长度的差;
- No时,少的个数对应于每个字母。比如样例中的输出 No 2,少的是 1个8 和 1个R,而并不是长度差。
处理方式:
- 处理输入:按 string 输入,for 遍历每个字符;
- 计数:for 遍历 摊主数组 和 小红数组 做计数。
- 数组:用新的 int 数组 cntBoss 和 cntBuyer 存放各个字符对应的值,下标则用组成 string 的不重复字符;
- 重复情况:我的方法可能会出现例如处理过一次 r 又遍历到了 r 这种情况,我的处理方法是用 flag 数组做标记。处理过后标记了的就不再处理;
- 全部满足的情况:就是到了遍历到最后 lack == 0 不变,而且cntBuyer [i] <= bossBuyer [i]。
代码:
# include <iostream>
# include <string>
using namespace std;
int main(){
string boss, buyer;
cin >> boss;
cin >> buyer;
int cntBoss[100000];
int cntBuyer[100000];
int flag[100000]; // flag 数组是为了在第三个 for 中处理时做标记。
int lack = 0; // 少的数量
int more = 0; // 多的数量
/* 输入并对每个boss buyer出现的字符进行计数 */
for (int i = 0; i < boss.length(); i++){
cntBoss[boss[i]]++;
}
for (int i = 0; i < buyer.length(); i++)
{
cntBuyer[buyer[i]]++; flag[buyer[i]] = 0;
}
/* 对比各个字符出现次数 决定输出 yes or no */
for (int i = 0; i < buyer.length(); i++){
if (cntBuyer[buyer[i]] > cntBoss[buyer[i]] && flag[buyer[i]] == 0) {
lack += (cntBuyer[buyer[i]] - cntBoss[buyer[i]]);
flag[buyer[i]] = 1; // 处理过了就不再处理
}
if (cntBuyer[buyer[i]] <= cntBoss[buyer[i]] && i == buyer.length() - 1 && lack == 0) {
more += (boss.length() - buyer.length());
}
}
if (lack > 0) cout << "No" << " " << lack; // 只要缺即 lack > 0 就是 No
else cout << "Yes" << " " << more;
return 0;
}
写在最后:
思路清晰,审题仔细不是一句空话。审题仔细让你在本题中明白输出的数字到底是怎么来的。
而实际上,很多看似空话的话并不是空话不是嘛。加油且坚持吧。