Leetcode第48场双周赛(4题)题解记录

5693.字符串中第二大的数字

给你一个混合字符串 s ,请你返回 s 中 第二大 的数字,如果不存在第二大的数字,请你返回 -1 。
混合字符串 由小写英文字母和数字组成。

暴力,数据范围较小,利用isdigit()判断是否为数字,结合set来做即可。
(学会set的rbegin()的使用)

class Solution {
public:
    int secondHighest(string s) {
        set<int> st;
        for(auto x :s){
            if(isdigit(x)){
                st.insert(x-'0');
            }
        }
        if(st.empty()|| st.size()==1) return -1;
        auto it = st.rbegin();
        it++;
        return *it;
    }
};

5694. 设计一个验证系统

关于验证码规则的简单模拟,题意比较明朗,关键在于time变量和验证码vector数组的维护,代码量不多。

class AuthenticationManager {
public:
    int time;
    vector<pair<string,int> > v;
    AuthenticationManager(int t) {
        time = t;
    }
    
    void generate(string id, int c) {
        v.push_back({id,c});
    }
    
    void renew(string id, int c) {
        vector<pair<string, int> > nv;
        for(int i=0;i<v.size();i++){
            auto x = v[i];
            if(id==x.first && x.second + time <= c){
                continue;
            }else if(id==x.first) {
                nv.push_back({id,c});
            }else {
                nv.push_back(x);
            }
        }
        v = nv;//新的vector替代旧的vector,少写for.
    }
    int countUnexpiredTokens(int c) {
        int ans = 0;
        for( auto x: v){
            if(c-x.second<time) ans++;
        }
        return ans;
    }
};

5712. 你能构造出连续值的最大数目

给你一个长度为 n 的整数数组 coins ,它代表你拥有的 n 个硬币。第 i 个硬币的值为 coins[i] 。如果你从这些硬币中选出一部分硬币,它们的和为 x ,那么称,你可以 构造 出 x 。
请返回从 0 开始(包括 0 ),你最多能 构造 出多少个连续整数
你可能有多个相同值的硬币。

转换成求多个数字的最小不能凑出来整数贪心思想,其实是比较coins[i]和sum[0…i-1]+1,如果前者大,sum[0…i-1]+1这个位置就是最小不能凑出来整数(可证明)。
(该题思维难度较高,脑筋急转弯,贪心思想不容易想到)

class Solution {
public:
    int getMaximumConsecutive(vector<int>& coins) {
        sort(coins.begin(),coins.end());
        int sum = 0;
        for(auto x:coins){
            if(x>sum+1) return sum+1;
            sum+=x;
        }
        return sum+1;
    }
};

5695. N 次操作后的最大分数和

给你 nums ,它是一个大小为 2 * n 的正整数数组。你必须对这个数组执行 n 次操作。
在第 i 次操作时(操作编号从 1 开始),你需要:
选择两个元素 x 和 y 。
获得分数 i * gcd(x, y) 。
将 x 和 y 从 nums 中删除。
请你返回 n 次操作后你能获得的分数和最大为多少。
函数 gcd(x, y) 是 x 和 y 的最大公约数。

注意官网说的测试数据范围,因为比较小,可以想到dfs或者状态dp,dfs可能会存在大量重复计算,估计会tle,其实本题是一道经典的状态DP模板题

class Solution {
public:
    int gcd(int a,int b){
        return b?  gcd(b,a%b) :a;
    }
    int maxScore(vector<int>& nums) {
        int mv = 0;
        int n = nums.size();//注意数据范围 nums.size()
        vector<int> f(1<<n);
        for(int i=0;i< 1<<n;i++){
            int cnt = 0;
            for(int j=0;j<n;j++){
                if(!(i>>j & 1)) //枚举i状态有多少个0
                    cnt++;
            }
            cnt = cnt/2+1;// cnt表示第几次,通过规律看i里面有多少个0得出第几次

            for(int j=0;j<n;j++)
                if(i>>j & 1) 
                    for(int k=j+1;k<n;k++)
                        if(i>>k & 1)
                            f[i] = max(f[i],f[i-(1<<j)-(1<<k)]+cnt*gcd(nums[k],nums[j]));
                            //递增式DP,因此直接返回f[(1<<n)-1]也可以
            mv = max(mv,f[i]);
        }
        return mv;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值