力扣第307场周赛 + 力扣第85场双周赛 + AcWing第65场周赛补题

力扣单周赛

一.赢得比赛需要的最少训练时长

1.原题链接:力扣

2.解题思路:

        记 X 为当前精力,Y为当前经验,我们先从 X = initialEnergy 与 Y = initialExperience 开始比赛。若 X <= energy[i],那么我们一开始至少需要增加 energy[i] - X + 1的精力,才能让现在的精力刚好超过对手 i 。若 Y <= experience[i],那么我们一开始至少需要增加 experience[i] - Y + 1 的经验,才能让现在的经验刚好超过对手 i 。用ans表示需要训练的最少小时数目。

3.参考代码:

class Solution {
public:
    int minNumberOfHours(int X, int Y, vector<int>& energy, vector<int>& experience) {
        int n = energy.size();
        int ans = 0;
        for (int i = 0; i < n; i++) {
            if (X <= energy[i]) {
                int t = energy[i] - X + 1;
                X += t;
                ans += t;
            }
            if (Y <= experience[i]) {
                int t = experience[i] - Y + 1;
                Y += t;
                ans += t;
            }
            X -= energy[i];
            Y += experience[i];
        }
        return ans;
    }
};

二.最大回文数字

1.原题链接:力扣

2.解题思路:

        首先使用一个数组记录0-9出现的次数,在满足回文数的条件下,最大的数出现在最前面更好,所以从9开始添加数字,如果计数每超过2就可以在前面和后面个添加一个9,最中间会选择从9-0中最大的单个数字,即计数%2==1,由于不能有前导0,需要使用一个flag标记前面是否有数字,而且还可能存在全是0的情况,此时需要输出"0"

3.参考代码:

class Solution {
public:
    string largestPalindromic(string num) {
        int n = num.size();
        int a[10];
        memset(a, 0, sizeof(a));
        for(int i = 0; i < n; i++){
            a[num[i] - '0']++;
        }
        int flag = 0;
        string result = "", result2 = "";
        for(int i = 9; i >= 0; i--){
            for(int j = 0; j < a[i] / 2; j++){
                if(i != 0)flag = 1;
                if(i == 0 && !flag)break;
                result += '0' + i;
            }
        }
        result2 = result;
        reverse(result2.begin(), result2.end());
        for(int i = 9; i >= 0; i--){
            if(a[i] % 2 == 1){
                result += '0'+i;
                break;
            }
        }
        if(result.size() == 0)return "0";
        return result + result2;
    }
};

力扣双周赛

一.得到K个黑块的最少涂色次数

1.原题链接:力扣

2.解题思路:

        实际上就是求长度为 K 的区间中最少有几个" W ",用双指针枚举所有长度为 K 的区间并取最小值即可。

3.参考代码:

class Solution {
public:
    int minimumRecolors(string blocks, int k) {
        int n = blocks.size();
        int cnt = 0;
        for (int i = 0; i < k; i++) if (blocks[i] == 'W') cnt++;
        int ans = cnt;
        for (int i = 1; i + k - 1 < n; i++) {
            if (blocks[i - 1] == 'W') cnt--;
            if (blocks[i + k - 1] == 'W') cnt++;
            ans = min(ans, cnt);
        }
        return ans;
    }
};

二.二进制字符串重新安排顺序需要的时间

1.原题链接:力扣

2.解题思路:

        动态规划

        1.题目的要求是将所有的1移动到最左侧;
        2.f[i]表示为重新排序s[0,i]所需的秒数;
        3.s[i]='0'时,f[i]=f[i-1],不需要额外移动;
        4.s[i]='1'时,前面如果没有0,不需要移动,
        前面如果有一个挨着的1,需要将1移走后,再移动当前的1;
        递推公式为: f[i]=max(f[i-1]+1, pre0)

3.参考代码:

class Solution {
public:
    int secondsToRemoveOccurrences(string s) {
        int n = s.size();
        vector<int> f(n);
        int pre0 = (s[0] == '0');

        for (int i = 1; i < n; i++) {
            if (s[i] == '0') {
                f[i] = f[i - 1];
                pre0++;
            } else if (pre0 > 0) {
                f[i] = max(f[i - 1] + 1, pre0);
            }
        }
        return f[n - 1];
    }
};

AcWing

一.最大价值

1.原题链接:4603. 最大价值 - AcWing题库

2.解题思路:

双指针(实际上是单指针)从头到尾遍历,是 P 就计数,是 A 就更新最大值,这里需要注意的边界就是当 i = -1 时会更新一次最大值,所以需要添加一个判断。

3.参考代码:

#include <iostream>
#include <algorithm>

using namespace std;

int main()
{
    int t;
    cin >> t;
    while (t -- )
    {
        int n;
        string str;
        cin >> n >> str;
        int res = 0;
        for (int i = str.size() - 1; i >= 0; i -- )
        {
            int tmp = 0;
            while (str[i] == 'P') i -- , tmp ++ ;
            if (i >= 0) res = max(res, tmp);
        }
        cout << res << endl;
    }
    return 0;
}

二.集合询问

1.原题链接:4604. 集合询问 - AcWing题库

2.解题思路:

         对于每一个字符串只需要将他们转化一种形式,比如说223132这个字符串,转换一下是001110,那么只需要在哈希表中存储1110即可,前缀0可以不用存储,对于每次查询也将前缀零不存储然后输出一下每个键所对用的值即可。

3.参考代码:

#include <iostream>
#include <unordered_map>
using namespace std;
unordered_map<string , int> ma;
int main(){
    int t;
    cin >> t;
    while(t --){
        char ar[2];
        string s1 , s2 = "";
        cin >> ar >> s1;
        for(int i = 0; i < s1.size(); i ++ ){
            if(s1[i] % 2 == 0) s2 += "0";
            else s2 += "1";
        }
        string s3 = "";
        for(int i = 0;i < s2.size(); i ++ ){
            if(s2[i] != '0' || i == s2.size() - 1){
                for(i ; i < s2.size(); i ++ )s3 += s2[i];
            }
        }
        if(*ar == '+') ma[s3] ++;
        else if(*ar == '-') ma[s3] --;
        if(*ar == '?'){
            cout << ma[s3] << endl;
        }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值