leetcode周赛375 - 12 - 10

比赛地址 :

 竞赛 - 力扣 (LeetCode)

t1

: 直接暴力即可

class Solution {
public:
    int countTestedDevices(vector<int>& b) {
        int n = b.size();
        int ans = 0;
        for(int i=0;i<n;i++){
            if(b[i]>0){
                ans ++;
                for(int j=i+1;j<n;j++){
                    b[j] = max(b[j]-1,0);
                }
            }
        }
        return ans;
    }
};

t2 : 

需要用到快速幂

typedef long long LL;
class Solution {
public:
    LL qmi(int m,int k,int p){
        int res = 1 % p,t =m;
        while(k){
            if(k&1) res = res * t % p ;
            t = t * t % p;
            k >>= 1;
        }
        return res;
    }
    vector<int> getGoodIndices(vector<vector<int>>& vs, int target) {
        int n = vs.size();
        vector<int> ans;
        // ((aibi % 10)ci) % mi == target
        for(int i=0;i<n;i++){
            int a = vs[i][0],b=vs[i][1],c=vs[i][2],m=vs[i][3];
            if( qmi(qmi(a,b,10),c,m) == target){
                ans.push_back(i);
            }
        }
        return ans;
    }
};

t3

滑动窗口 : 维护一个窗口( l , r ) 使其中的最大值出现的次数为k次,小于k的时候,r向后遍历,直到出现次数==k,这时候,删除窗口左边的数字,使最大值出现次数<k,然后这样循环遍历即可;

class Solution {
public:
    long long countSubarrays(vector<int>& nums, int k) {
        long long ans = 0;
        int n = nums.size();
        int l = 0 , r = 0 ;
        int ma = *max_element(nums.begin(),nums.end());
        int t = 0 ;// 统计窗口中ma出现的次数
        while(r < n){
            t += nums[r] == ma;
            while(t==k){
                t -= nums[l++]==ma;
            }
            ans += l ; // 以r为右端点的,以l为左端点的,那么l之前的都可以(能够很好的去重)
            r ++ ; 
        } 
        return ans ;
    }
};

t4:

首先重复元素肯定只能够出现在一个数组里面,那么就可以使用类似于lc56区间合并的思想了,具体实现请看代码 : 

const int mod = 1e9+7;
class Solution {
public:
    int numberOfGoodPartitions(vector<int>& nums) {
        // 每个重复元素必须选择 , 然后类似区间合并
        unordered_map<int,pair<int,int>> mp;
        int n = nums.size();
        for(int i=0;i<n;i++) // 找出每个数字的首尾地址
            if(mp.find(nums[i])==mp.end()) // 之前没有出现过
                mp[nums[i]] = {i, i} ;
            else{ // 之前出现过
                mp[nums[i]].second = i; 
            }
        vector<pair<int,int>> a;
        for(auto &[_,p]:mp) a.push_back(p);
        sort(a.begin(),a.end(),[](const auto &p,const auto &q){
            return p.first < q.first ; // 按区间的左端点排序
        });
        // 下面就是合并区间的思想了,看下能够最多分成 m 个区间
        // ans = 2 ^ (m - 1)  
        int ans = 1; // 最少就是整个数组的一种选法
        int idx = a[0].second;
        for(int i=1;i<a.size();i++){
            int l = a[i].first , r = a[i].second;
            if(l>idx){// 新开一个区间
                ans = ans * 2 % mod;
            } 
            idx = max(idx , r);
        }
        return ans;
    }
};

  • 5
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值