【C++】 —— 笔试刷题day_25
一、笨小猴
题目解析

这道题,给定一个字符
str,让我们找到这个字符串中出现次数最多字母的出现次数maxn和出现次数最少字母的出现次数minn;然后判断
maxn - minn是否是一个质数,如果是就输出Lucky Word和maxn - minn;如果不是就输出No Answer和0。
算法思路
OK啊,这道题可以说是比较简单的,我们只需要遍历字符串str,记录出现次数最多字母的出现次数maxn和出现次数最少字母的次数minn,然后判断maxn - minn是否是一个质数即可。
统计每一个字符出现的次数
遍历字符串str,统计每一个字符出现的次数(题目中说明:只存在小写字母,所以可以使用int cnt[26]来统计每一个字符出现的次数)
找到maxn和minn
统计完每个字母出现的次数以后,在遍历str,找到在str中出现过的字母的出现次数的最大值maxn和最小值minn即可;
判断maxn - minn是否是一个质数
判断一个数是否是质数,这个就比较简单了;这里就不叙述了。
代码实现
#include <iostream>
#include <cmath>
using namespace std;int cnt[26];
string str;
bool isprim(int x) {if (x < 2)return false;for (int i = 2; i <= sqrt(x); i++) {if (x % i == 0)return false;}return true;
}
int main() {cin >> str;for (auto& e : str) {cnt[e - 'a']++;}int maxn = 0, minn = str.size() + 1;for (auto& e : str) {maxn = max(maxn, cnt[e - 'a']);minn = min(minn, cnt[e - 'a']);}if (isprim(maxn - minn))cout << "Lucky Word" << endl << maxn - minn << endl;elsecout << "No Answer" << endl << 0 << endl;return 0;
}
二、主持人调度(一)
题目解析

这道题,就有意思了;现在有
n个活动,每一个活动都有开始时间start和结束时间end,在某一个时间内,一个主持人只能主持一个活动;现在要求我们判断只有一个主持人的情况下能否举办全部的活动?简单来说就是,让我们判断中某时间,是否存到多个活动同时举办;也就是说这些活动举办的时间不能有重复的部分。
算法思路
OK啊,这道题让我们判断能不能举办全部的活动,说的通俗一点就是让我们判断这些活动的举办时间(开始时间 - 结束时间)是否有重复的时间段。
那我们如何去判断呢?
在初次看到这道题时,博主的思路:使用一个表来记录每一个时间是否有活动在举行但是这样就太复杂了
- 对于这道题我们可以直接对给定的数组进行排序,这样所有活动就是按照开始时间升序排序的,也就是说从先开始的活动是排在前面的;
- 然后我们排序后的数组,从前往后遍历,只需判断一个活动开始时,前一个活动有没有结束即可(或者一个好的结束时,有没有到达后一个活动的开始时间)。
代码实现
class Solution {
public:bool hostschedule(vector<vector<int> >& schedule) {sort(schedule.begin(),schedule.end());for(int i = 1;i<schedule.size();i++){if(schedule[i-1][1] > schedule[i][0])return false;}return true;}
};
三、分割等和子集
题目解析

这道题,题目给定一个只包含正整数的数组
nums,然后让我们判断,能否将数组中的若干个数取出,使得取出的数和剩下的数之和相等;简单来说就是在数组中选择若干个数,使得这些数的和等于所有数和的一半。
算法思路
初次看到这道题,可以说毫无思路;
这里就直接说解法了:动态规划 - 01背包问题
看到这道题解法可能有疑问:这怎么去用动态规划啊?
我们这道题,让我们在一个数组找若干个数,这些数的和等于num/2;那是不是可以理解为,在n个数中寻找和为num/2的若干个数。
OK啊,了解了这道题要使用动态规划去解决,那状态表示和状态转移方程该如何去找呢?
这里题目只要求我们判断能否找到,所以我们只需要知道在
n个数中是否存在和为num/2的若干个数即可。状态表示:
dp[i][j]表示在i个数中是否存在和为j的若干个数。
状态转移方程:对于第
i个数nums[i],我们要考虑的就只有选还是不选这个数:如果选第
i个数,我们就要在前i-1个数中看是否能找到和为j - nums[i]的若干个数(dp[i-1][j - nums[i]);如果不选第
i个数,我们就要在前i-1个数中看是否能找到和为j的若干个数(dp[i-1][j])。
而我们只需要知道是否能够找到即可,无需考虑是否选择第
i个数;所以状态转移方程:dp[i][j] = dp[i-1][j] || dp[i-1][j-nums[i]];最后我们还要注意,判断是否能选第
i个数:如果nums[i] > j就表示不能选择第i个数。初始化:
这里我们只需要初始化
dp[0][0]就可以了(按理来说,我们需要将第0列的所有位置填成true;因为其表示在i个数中选择和为0的数,肯定是存在的(不选不就OK了))将
dp[0][0]初始化成true,在填表时,第一列也就会被填成true。
当然这道题在填表之前,我们还要求nums中所有数的和,咱进行一下判断:如果所有数的和sum为奇数,那我们可以是找不到的(因为题目上说了所有数都是正整数);
最后我们只需要看dp[n][sum/2]位置是true还是false即可
代码实现
#include <iostream>
using namespace std;
int nums[501];
bool dp[501][50001];
int n;
int main() {cin >> n;int sum = 0;for (int i = 0; i < n; i++) {cin >> nums[i];sum += nums[i];}if (sum % 2 == 1) {cout << "false" << endl;return 0;}dp[0][0] = true;for (int i = 1; i <= n; i++) {for (int j = 0; j <= sum / 2; j++) {if (nums[i] > j)dp[i][j] = dp[i - 1][j];else {dp[i][j] = dp[i - 1][j] || dp[i - 1][j - nums[i]];}}}if (dp[n][sum / 2])cout << "true" << endl;elsecout << "false" << endl;return 0;
}
到这里本篇文章就结束了,感谢各位的支持
 继续加油!!!
