第一题:6229. 对数组执行操作
思路:开辟一个新数组来存储,然后遍历最后赋值即可
class Solution { public: vector<int> applyOperations(vector<int>& nums) { for(int i = 0; i < nums.size() - 1; i++) { if(nums[i] == nums[i+1]) nums[i] *= 2, nums[i+1] = 0; } vector<int> res; for(int i = 0; i < nums.size(); i++) { if(nums[i] == 0) continue; res.push_back(nums[i]); } for(int i = 0; i < res.size(); i++) { nums[i] = res[i]; } for(int i = res.size(); i < nums.size(); i++) nums[i] = 0; return nums; } };
第二题:6230. 长度为 K 子数组中的最大和
思路:滑动窗口题,开始想用队列写,但是又想到k个数里不能有重复,而且它们可能不是连续的,所以队列写也不太好。用哈希表,先存入前k个,然后将窗口向后滑动,确保mp的个数为k就保证了数组里没有重复,否则不满足条件继续滑动,直到结束取最优解即可
class Solution { public: typedef long long LL; long long maximumSubarraySum(vector<int>& nums, int k) { LL res=0,tmp=0; int n=nums.size(); unordered_map<int,int> mp; for(int i=0;i<k;i++){ tmp+=nums[i]; mp[nums[i]]++; } if(mp.size()==k) res=max(res,tmp); for(int i=k;i<n;i++){ tmp-=nums[i-k]; tmp+=nums[i]; mp[nums[i-k]]--; mp[nums[i]]++; if(mp[nums[i-k]]==0) mp.erase(nums[i-k]); if(mp.size()==k&&tmp>res) res=tmp; } return res; } };
第三题:6231. 雇佣 K 位工人的总代价
思路:暴力过了大半数据,然后因为范围在1e5,会超时,然后用pair排序优化了一下又过了几个数据,但是还是没有ac。最好的方法就是用小根堆,维护左右两个小根堆,然后比较堆顶选更小的即可,注意将res用long long 来存储,int会爆掉。
class Solution { public: long long totalCost(vector<int>& costs, int k, int candidates) { priority_queue<int, vector<int>, greater<>> p, q; long long res = 0;//开大一点不然会溢出 int i = 0; int j = costs.size() - 1; while (k--) { /* 从左右分别选candidates个候选 */ while (p.size() < candidates && i <= j) { p.push(costs[i++]); } while (q.size() < candidates && i <= j) { q.push(costs[j--]); } /* 找到最小值, 相同时选小标更小的 */ int a = (p.size() > 0) ? p.top() : INT_MAX; int b = (q.size() > 0) ? q.top() : INT_MAX; if (a <= b) { /* 累加当前代价最小的 */ res += a; p.pop(); } else { res += b; q.pop(); } } return res; } };