Q1 统计已测试设备
-
解题思路:
- 从左向右遍历
- 用一个变量cnt记录在当前位置左侧已经有多少个已测试设备
- 在当前位置,检查max(batteryPercentages[i] - cnt, 0)是否大于0,如果大于0,更新cnt
-
解题代码:
class Solution {
public:
int countTestedDevices(vector<int>& batteryPercentages) {
int cnt = 0;
for(auto bp : batteryPercentages)
{
int temp = max(bp - cnt, 0);
if(temp > 0)
cnt += 1;
}
return cnt;
}
};
Q2 双横幂运算
-
解题思路:
- 数据范围并不大
- 利用迭代模拟求幂操作即可
-
解题代码:
class Solution {
public:
vector<int> getGoodIndices(vector<vector<int>>& variables, int target) {
vector<int> ans;
int n = variables.size();
for(int i = 0; i < n; i++)
{
int a = variables[i][0], b = variables[i][1], c = variables[i][2], m = variables[i][3];
int temp = 1;
for(int j = 1; j <= b; j++)
temp = temp * a % 10;
a = temp;
for(int j = 1; j < c; j++)
temp = temp * a % m;
if(temp % m == target)
ans.push_back(i);
}
return ans;
}
};
Q3 统计最大元素出现至少K次的子数组
-
解题思路:
- 先找到数组中的最大元素
- 滑动窗口,向右移动right指针,同时向右移动left指针,直到满足[left, right]中最大元素恰好出现k次,并且left位置的元素刚好是最大元素,此时可以组成left+1个满足条件的子数组,更新到答案中
-
解题代码:
class Solution {
public:
long long countSubarrays(vector<int>& nums, int k) {
long long ans = 0;
int mx = *max_element(nums.begin(), nums.end());
int left = 0, right = 0;
int n = nums.size();
int cnt = 0;
while(right < n)
{
if(nums[right] == mx)
cnt += 1;
while(cnt > k || (cnt == k && nums[left] != mx))
{
if(nums[left] == mx)
cnt -= 1;
left += 1;
}
if(cnt == k)
ans += left + 1;
right += 1;
}
return ans;
}
};
Q4 统计好分割方案的数目
-
解题思路:
- 首先统计数组中各元素的出现位置
- 对于出现多次的元素,其第一次出现与其最后一次出现构成一个区间,该区间内的数必须分在同一组
- 合并上述的区间
- 这些合并后的区间只可以整体一组
- 假设两个区间之间有m个数,这m个数共有2^(m-1)种分割法
- 将两区间之间的数也看作整体,假设一共有n个整体,这n个整体共有2^(n-1)种方法
-
解题代码:
class Solution {
public:
const int MOD = 1e9 + 7;
long long myPow(long long a, int n)
{
if(n == 0)
return 1;
if(n & 1)
return a * myPow(a, n-1) % MOD;
long long temp = myPow(a, n/2);
return temp * temp % MOD;
}
int numberOfGoodPartitions(vector<int>& nums) {
unordered_map<int, vector<int>> um;
int n = nums.size();
for(int i = 0; i < n; i++)
um[nums[i]].push_back(i);
vector<pair<int, int>> intervals;
for(auto &it : um)
{
vector<int>& idxs = it.second;
if(idxs.size() < 2)
continue;
intervals.push_back({idxs[0], idxs.back()});
}
//合并区间
int len = intervals.size();
if(len == 0)//没有区间
return myPow(2, n-1);
sort(intervals.begin(), intervals.end());
int curLeft = intervals[0].first, curRight = intervals[0].second;
vector<pair<int, int>> newIntervals;
for(int i = 1; i < len; i++)
{
auto [l, r] = intervals[i];
if(l < curRight)//合并
{
curRight = max(r, curRight);
continue;
}
//不合并
newIntervals.push_back({curLeft, curRight});
curLeft = l;
curRight = r;
}
newIntervals.push_back({curLeft, curRight});
//计算方案数
long long ans = 1;
int left = 0;
int cnt = 0;
for(auto [l, r] : newIntervals)
{
cnt += 1;
if(l != left)
{
ans = ans * myPow(2, l-left-1) % MOD;
cnt += 1;
}
left = r + 1;
}
if(n != left)
{
ans = ans * myPow(2, n-left-1) % MOD;
cnt += 1;
}
ans = ans * myPow(2, cnt-1) % MOD;
return ans;
}
};