比赛地址 :
竞赛 - 力扣 (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 == targetfor(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;}
};