2779. 数组的最大美丽值 - 力扣(LeetCode)

Solution
这题有两种做法,一个是定长的滑动窗口一个是变长的滑动窗口。
首先看我自己的想法,受740. 删除并获得点数 - 力扣(LeetCode) 的启发,这题可以映射到值域,然后求窗口大小为2*k+1的最大窗口累加和。
这种做法的时间复杂度是O(n),但是空间复杂度较高,取决于数组的最大值。
cpp
int maximumBeauty(vector<int>& nums, int k) {
int n = nums.size();
int maxNum = ranges::max(nums);
vector<int> value_count(maxNum + 1, 0);
long long sumNum = 0;
for (int i = 0; i < n; ++i) {
value_count[nums[i]]++;
sumNum += nums[i];
}
int len = 2 * k + 1, window_count = 0, ans = 0;
if (len >= maxNum)
return n;
for (int r = 0; r <= maxNum; ++r) {
window_count += value_count[r];
int l = r - len + 1;
if (l >= 0) {
ans = max(ans, window_count);
}
if (l >= 0) {
window_count -= value_count[l];
}
}
return ans;
}
第二种做法也是比较有启发价值的,由于要求的是子序列的长度,跟数组的顺序无关,所以可以对数组进行排序,排完序之后就很直观清晰了,求一个区间,这个区间满足最大值和最小值之差小于等于2*k,求这个区间的最大长度,也是很典型的变长滑动窗口问题。
跟3634. 使数组平衡的最少移除数目 - 力扣(LeetCode)很相似,都是排序之后的变长滑动窗口。
cpp
int maximumBeauty(vector<int>& nums, int k) {
int n = nums.size();
sort(nums.begin(), nums.end());
int l = 0, ans = 0;
for (int r = 0; r < n; ++r) {
while (nums[r] - nums[l] > 2 * k) {
l++;
}
ans = max(ans, r - l + 1);
}
return ans;
}