第四题:找出最长等值数组
-
滑动窗口
-
总长度 - 众数 > k
就需要收缩窗口了。 -
所以需要一个数据结构统计众数:
multiset
维护每一个数字的个数。
这里有一个坑ms.erase(x)
:会把所有的等于x的数字都删除。所以需要使用auto it = ms.find(x); ms.erase(it)
来进行单个删除。
class Solution {
public:
int longestEqualSubarray(vector<int>& nums, int k) {
int n = nums.size();
multiset<int>ms;
unordered_map<int, int>cnt;
int ans = 0;
for (int i = 0, j = 0; j < n; j++) {
del(ms, cnt[nums[j]]);
cnt[nums[j]]++;
ms.insert(cnt[nums[j]]);
int c_cnt = *(ms.rbegin());
// 长度 - 众数 > k收缩窗口
while (j - i + 1 - c_cnt > k) {
del(ms, cnt[nums[i]]);
cnt[nums[i]]--;
ms.insert(cnt[nums[i]]);
i++;
c_cnt = *(ms.rbegin());
}
ans = max(ans, *(ms.rbegin()));
}
return ans;
}
// 单点删除
void del(multiset<int>&ms, int target) {
auto it = ms.find(target);
if (it != ms.end()) {
ms.erase(it);
}
}
};
第三题:销售利润最大化
-
排序 + 二分 + dp
-
类似于学最多的课程,按照结尾进行排序
-
排序之后,定义
f[i]
:截止到i为止的最大值,f[i] = max(f[i - 1], f[pre] + g)
文章来源:https://www.toymoban.com/news/detail-661279.html -
pre
是前面最后一个可以购买的下标。因为排序了所以可以使用二分找到第一个ed < cur_bg
的下标pre
文章来源地址https://www.toymoban.com/news/detail-661279.html
class Solution {
public int maximizeTheProfit(int n, List<List<Integer>> offers) {
// 区间最大值,可以按照开始进行排序,可以按照结尾进行排序。这里选择按照结尾进行排序
// 如果区间相交,那么就不能进行同时购买,否则就可以进行同时购买。
// f[i]:表示截止到区间i的最大值
// 可以二分找到前面可以购买的第一个房间lower_boudn() - 1。f[i] = f[pre] + goal[i];
// 状态转移是否有问题。有,截止到当前的,那么就不是以当前结尾的。如果表示当前结尾的,那么需要遍历前面所有小于它的。
// 如果表示截至到当前的, f[i] = Math.max(f[i - 1], f[pre] + offers.get(i).get(2));
// 第二种状态:当前可以买,可以不买,买
offers.sort(new Comparator<List<Integer>>() {
@Override
public int compare(List<Integer> o1, List<Integer> o2) {
return Integer.compare(o1.get(1), o2.get(1));
}
});
int len = offers.size();
int[] f = new int[len + 1];
for (int i = 1; i <= len; i++) {
int bg = offers.get(i - 1).get(0), ed = offers.get(i - 1).get(1);
int g = offers.get(i - 1).get(2);
int l = 0, r = len;
while (l < r) {
int mid = (l + r) >> 1;
if (offers.get(mid).get(1) >= bg) r = mid;
else l = mid + 1;
}
f[i] = Math.max(f[l] + g, f[i - 1]);
// System.out.println("l = " + l);
// System.out.println(f[i]);
}
return f[len];
}
}
第二题 k-avoiding
- 小贪心
- 为了避免会出现和为k的情况。如果出现x就不能出现k - x,由于需要的数组和最小,所以选择min(x, k - x)
- 由于数组和最小,所以可以直接从1开始进行取数,如果选则了x,就不能选择k - x,使用
map
或者set
进行标记就行了。
class Solution {
public:
int minimumSum(int n, int k) {
// 什么情况下会出现和为k的情况。如果出现x就不能出现k - x。那么选择x还是k - x呢?肯定选择min(x, k - x);
// 最小不同,所以对于每一个数字,从最小的可以选的选择。
unordered_map<int, int>mp;
int cur = 1;
int ans = 0;
for (int i = 0; i < n; i++) {
while (mp[cur] == 1) cur++;
ans += cur;
mp[k - cur] = 1;
cur++;
}
return ans;
}
};
到了这里,关于leetcode359周赛的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!