一、双周赛 85
1、2379.得到K个黑块的最少涂色
(1)原题链接:力扣
https://leetcode.cn/problems/minimum-recolors-to-get-k-consecutive-black-blocks/
(2)解题思路:
统计窗口长度为 k 且黑块最多的数量,然后用 k 减去这个数量就是要改变的最小涂色。
(3)代码:
class Solution {
public:
int minimumRecolors(string blocks, int k) {
int res = 0;
int cnt = 0;
for(int i = 0; i <= blocks.size() - k; i ++ ) {
int tmp = 0;
for(int j = i; j < k + i; j ++ ) {
if(blocks[j] == 'B') tmp ++;
}
if(tmp >= cnt) {
cnt = tmp;
}
}
return k - cnt;
}
};
2、2380.二进制字符串重新安排顺序需要的时间
(1)原题链接:力扣
https://leetcode.cn/problems/time-needed-to-rearrange-a-binary-string/
(2)解题思路:
从 01 -> 10 可以看作是 1 的左移,但 1 的左边为 1 时不可移动。
所以,最终的时间取决于 1 的左边最多有多少个 0 ,0 的个数就是需要的时间,但,我们还需要考虑,若这个有最多个 0 在左边的 1 的左边还存在 1 那么此时需要的时间需要加一。
(3)代码:
class Solution {
public:
int secondsToRemoveOccurrences(string s) {
int res = 0;
int cnt = 0;
for(int i = 0; i < s.size(); i ++ ) {
if(s[i] == '0') cnt ++;
else if(cnt > 0) res = max(res + 1, cnt);
}
return res;
}
};
3、2381.字母移位II
(1)原题链接:力扣
https://leetcode.cn/problems/shifting-letters-ii/
(2)解题思路:
本题考点前缀和。
用一个数组保存,所有操作带来的变化,运用前缀和的思想。往前前移就在开始位置加1,结束位置+1(因为包含结束位置)的位置减1,往后移动则相反。最后,一次遍历执行操作,改变字符串。
(3)代码:
class Solution {
public:
string shiftingLetters(string s, vector<vector<int>>& shifts) {
int n = s.size(), m = shifts.size();
int a[n + 1];
memset(a, 0, sizeof(a));
for(int i = 0; i < m; i ++ ) {
int tmp = 1;
if(shifts[i][2] == 0) tmp = -1;
a[shifts[i][0]] += tmp;
a[shifts[i][1] + 1] -= tmp;
}
int sum = a[0];
for(int i = 0; i < n; i ++ ) {
int tmp = (s[i] - 'a' + sum) % 26;
if(tmp < 0) tmp += 26;
s[i] = tmp + 'a';
sum += a[i + 1];
}
return s;
}
};
二、单周赛 307
1、2383.赢得比赛需要的最少训练时长
(1)原题链接:力扣
https://leetcode.cn/problems/minimum-hours-of-training-to-win-a-competition/
(2)解题思路:
首先,由题可知,我们所需的精力是一定的是不会增长的,所以我们必须先保证初始精力值严格大于赢得比赛所需精力值,其次,我们再遍历energy数组,若当前经验小于energy [i],那么我们就加上energy [i] - 当前精力 + 1 的训练时长,最终所得即答案。
(3)代码:
class Solution {
public:
int minNumberOfHours(int initialEnergy, int initialExperience, vector<int>& energy, vector<int>& experience) {
int sum = 0;
for(auto& a: energy) sum += a;
int res = 0;
if(sum >= initialEnergy) res += sum - initialEnergy + 1;
for(auto& c: experience) {
if(initialExperience <= c) {
int tmp = c - initialExperience + 1;
initialExperience += tmp + c;
res += tmp;
}
else initialExperience += c;
}
return res;
}
};
2、2384.最大回文数字
(1)原题链接:力扣
https://leetcode.cn/problems/largest-palindromic-number/
(2)解题思路:
首先,保存每个数字出现的次数,然后判断是否存在某个大于零的数的个数大于等于2,若不存在则返回当前存在的最大的数(位数为1)。
然后,求答案字符串的前半部分,从9遍历到0,若存在数字的个数大于等于2的就加到答案字符串中,然后再遍历找到进行完上述操作后存在的最大数字作为答案字符串最中间的那个数字,最后再加上前半部分的翻转后的字符串就得到了最终的结果。
(3)代码:
class Solution {
public:
string largestPalindromic(string num) {
int cnt[10] = {0};
for(auto& c: num) cnt[c - '0'] ++;
string res;
for(int i = 9; i ; i -- ) {
if(cnt[i] >= 2) {
res = to_string(i);
cnt[i] -= 2;
break;
}
}
if(res == "") {
for(int i = 9; i >= 0; i -- ) {
if(cnt[i]) return to_string(i);
}
}
for(int i = 9; i >= 0; i -- ) {
while(cnt[i] >= 2) {
res += to_string(i);
cnt[i] -= 2;
}
}
string tmp = res;
reverse(tmp.begin(), tmp.end());
for(int i = 9; i >= 0; i -- ) {
if(cnt[i]) {
res += to_string(i);
break;
}
}
return res + tmp;
}
};