五月集训(第04天)——贪心
贪心
1. 1221. 分割平衡字符串
思路:
分割成尽可能多的字符串,从头开始遍历字符串,每遇到一个平衡字符串,结果加一。利用一个left_cnt记录出现的单个L的数量,遇到L => left_cnt++,遇到R => left_cnt--,当left_cnt == 0 时即L,R的数量相等,为一个平衡字符串。
class Solution {
public:
int balancedStringSplit(string s) {
int ans = 0;
int len = s.size();
int left_cnt = 0;
for (int i = 0; i < len; i++) {
if (s[i] == 'L') left_cnt ++;
else left_cnt --;
if (left_cnt == 0) ans ++;
}
return ans;
}
};
2. 1827. 最少操作使数组递增
思路:
需要让数组严格单调递增,于是如果num[i] >= nums[i + 1]那么最少的操作数是让nums[i + 1] = nums[i] + 1,即一次的操作数为nums[i] + 1 - nums[i + 1]
class Solution {
public:
int minOperations(vector<int>& nums) {
int n = nums.size();
int ans = 0;
for (int i = 0; i < n - 1; i++) {
if (nums[i] >= nums[i + 1]) {
ans += (nums[i] + 1 - nums[i + 1]);
nums[i + 1] = nums[i] + 1;
}
}
return ans;
}
};
3. 2144. 打折购买糖果的最小开销
思路:
对数组从大到小排序,贪心的买最大的两个,赠送次大的一个。即以3个为一组进行购买,最后考虑余数,把剩下的一个或两个直接购买即可。
class Solution {
public:
int minimumCost(vector<int>& cost) {
int n = cost.size();
int step = 3, times = n / 3, rest = n % 3;
int ans = 0;
sort(cost.begin(), cost.end(), greater<int>());
for (int i = 0; i < times; i++) {
ans += cost[i*step] + cost[i*step+1];
}
if (rest == 1) ans += cost[n - 1];
else if (rest == 2) ans += cost[n - 2] + cost[n - 1];
return ans;
}
};
4. 1400. 构造 K 个回文字符串
思路:
此题主要是考虑字符串中有多少个字母出现了奇数次。因为出现奇数次的字符串之间不能通过合并产生回文串,所以必须有odds_num < strlen(s)(出现奇数次的字母的数量小于字符串的长度),这样不够的部分部分就可以用偶数次的字母补上(偶数次的字母可以任意组合成回文串),或者将奇数次的字母拆开。但前提是字母的数量要足够多,至少能构成k个由一个字母构成的字符串。
class Solution {
public:
bool canConstruct(string s, int k) {
vector<int> my_hash(26, 0);
int len = s.length();
int odds_num = 0;
for (int i = 0; i < len; i++) my_hash[s[i] - 'a'] ++;
for (int i = 0; i < 26; i++) if (my_hash[i] & 1) odds_num ++;
return (odds_num <= k && k <= len);
}
};
东方欲晓,莫道君行早。

浙公网安备 33010602011771号