• 第318场周赛


    第 318 场周赛 - 力扣(LeetCode)icon-default.png?t=M85Bhttps://leetcode.cn/contest/weekly-contest-318/

    今天只更新三道题,嘿嘿。

    2460. 对数组执行操作-Easy

    题目描述:

    给你一个下标从 0 开始的数组 nums ,数组大小为 n ,且由 非负 整数组成。

    你需要对数组执行 n - 1 步操作,其中第 i 步操作(从 0 开始计数)要求对 nums 中第 i 个元素执行下述指令:

    如果 nums[i] == nums[i + 1] ,则 nums[i] 的值变成原来的 2 倍,nums[i + 1] 的值变成 0 。否则,跳过这步操作。
    在执行完 全部 操作后,将所有 0 移动 到数组的 末尾 。

    例如,数组 [1,0,2,0,0,1] 将所有 0 移动到末尾后变为 [1,2,1,0,0,0] 。
    返回结果数组。

    注意 操作应当 依次有序 执行,而不是一次性全部执行。

    题目解析:

    使用一个数组进行数值存储,只需将不为0的数压入存储即可,然后将数组补0至长度与原数组相同,代码如下:

    1. class Solution {
    2. public:
    3. vector<int> applyOperations(vector<int>& nums) {
    4. int len = nums.size();
    5. vector<int> res(len);
    6. for(int i = 0 ; i-1 ; i++){
    7. if(nums[i+1]==nums[i]){
    8. nums[i] *= 2;
    9. nums[i+1] = 0;
    10. }
    11. }
    12. int pos = 0;
    13. for(int i = 0 ; i
    14. if(nums[i]!=0)res[pos++] = nums[i];
    15. }
    16. return res;
    17. }
    18. };

    也可以通过原地修改,实现O(1)的空间复杂度,代码如下:

    1. // O(1)的空间
    2. class Solution {
    3. public:
    4. vector<int> applyOperations(vector<int>& nums) {
    5. int len = nums.size();
    6. int pos = 0;
    7. for(int i = 0 ; i-1 ; i++){
    8. if(nums[i]==0)continue;
    9. if(nums[i]==nums[i+1]){
    10. nums[i] *= 2;
    11. nums[i+1] = 0;
    12. }
    13. nums[pos++] = nums[i];
    14. }
    15. nums[pos++] = nums[len-1];
    16. for(int i = pos ; i
    17. nums[i] = 0;
    18. }
    19. return nums;
    20. }
    21. };


    2461. 长度为K子数组中的最大和-Medium

    题目描述:

    给你一个整数数组 nums 和一个整数 k 。请你从 nums 中满足下述条件的全部子数组中找出最大子数组和:

    子数组的长度是 k,且
    子数组中的所有元素 各不相同 。
    返回满足题面要求的最大子数组和。如果不存在子数组满足这些条件,返回 0 。

    子数组 是数组中一段连续非空的元素序列。

    题目解析:

    滑动窗口,使用一个unordered_set来保证窗口内不存在重复元素,如果有重复元素则左边界右移一位,直到窗口内不存在重复元素后,移动右边界,当窗口大小为K时,进行输出值判断,值的更新只需要在原有窗口的值总和上判断右边界和左边界的移动加减对应的数值即可,代码如下:

    1. class Solution {
    2. public:
    3. long long maximumSubarraySum(vector<int>& nums, int k) {
    4. int len = nums.size();
    5. int left = 0;
    6. int right = 0;
    7. unordered_set<int> uset;
    8. long long temp = 0;
    9. long long res = 0;
    10. while(right
    11. if(uset.count(nums[right])==1||right-left==k){
    12. uset.erase(nums[left]);
    13. temp -= nums[left];
    14. left++;
    15. }
    16. else{
    17. uset.emplace(nums[right]);
    18. temp += nums[right++];
    19. if(right-left==k)res = max(res,temp);
    20. }
    21. }
    22. return res;
    23. }
    24. };

    执行用时:220 ms, 在所有 C++ 提交中击败了100.00%的用户

    内存消耗:92.1 MB, 在所有 C++ 提交中击败了100.00%的用户


    2462. 雇佣K位工人的总代价

    题目描述:

    给你一个下标从 0 开始的整数数组 costs ,其中 costs[i] 是雇佣第 i 位工人的代价。

    同时给你两个整数 k 和 candidates 。我们想根据以下规则恰好雇佣 k 位工人:

    总共进行 k 轮雇佣,且每一轮恰好雇佣一位工人。
    在每一轮雇佣中,从最前面 candidates 和最后面 candidates 人中选出代价最小的一位工人,如果有多位代价相同且最小的工人,选择下标更小的一位工人。
    比方说,costs = [3,2,7,7,1,2] 且 candidates = 2 ,第一轮雇佣中,我们选择第 4 位工人,因为他的代价最小 [3,2,7,7,1,2] 。
    第二轮雇佣,我们选择第 1 位工人,因为他们的代价与第 4 位工人一样都是最小代价,而且下标更小,[3,2,7,7,2] 。注意每一轮雇佣后,剩余工人的下标可能会发生变化。
    如果剩余员工数目不足 candidates 人,那么下一轮雇佣他们中代价最小的一人,如果有多位代价相同且最小的工人,选择下标更小的一位工人。
    一位工人只能被选择一次。
    返回雇佣恰好 k 位工人的总代价。

    题目解析:

    这道题是我最遗憾的,我用了一个小根堆来进行维护左右两边的最小值,然后将每个值对应的坐标从小到大进行hashmap存储,小根堆弹出一个值,查找对应的哈希表中最小坐标在左边界还是右边界进行边界的更新和数据入堆,并将对应坐标从哈希表中删除,这导致了超时,今天看了眼答案,直接两个堆分别维护左右边界内的值,如果左堆顶小于等于右堆顶,弹出即可,不需要进行坐标的判断,因为左边界内的坐标肯定小于右边界的坐标,随后根据边界条件进行后续处理即可。

    这里需要注意的是,如果在计算过程中,左边界大于右边界了,这时就不需要进行边界更新了,根据堆顶大小依次弹出即可,代码如下:

    1. class Solution {
    2. public:
    3. long long totalCost(vector<int>& costs, int k, int candidates) {
    4. int len = costs.size();
    5. int std = k;
    6. long long ans = 0;
    7. if(2*candidates
    8. priority_queue<int,vector<int>,greater<int>> heap_l;
    9. priority_queue<int,vector<int>,greater<int>> heap_r;
    10. int left = 0 , right = len-1;
    11. for( ; left
    12. heap_l.push(costs[left++]);
    13. }
    14. for( ; right>=len-candidates ;){
    15. heap_r.push(costs[right--]);
    16. }
    17. while(k>0&&left<=right){
    18. if(heap_l.top()<=heap_r.top()){
    19. ans += heap_l.top();
    20. heap_l.pop();
    21. heap_l.push(costs[left++]);
    22. }
    23. else{
    24. ans += heap_r.top();
    25. heap_r.pop();
    26. heap_r.push(costs[right--]);
    27. }
    28. k--;
    29. }
    30. while(k>0){
    31. if(!heap_l.empty()&&heap_l.top()<=heap_r.top()){
    32. ans += heap_l.top();
    33. heap_l.pop();
    34. }
    35. else{
    36. ans += heap_r.top();
    37. heap_r.pop();
    38. }
    39. k--;
    40. }
    41. }
    42. else{
    43. sort(costs.begin(),costs.end());
    44. for(int i = 0 ; i
    45. ans += costs[i];
    46. }
    47. }
    48. return ans;
    49. }
    50. };

    执行用时:160 ms, 在所有 C++ 提交中击败了100.00%的用户

    内存消耗:68.7 MB, 在所有 C++ 提交中击败了100.00%的用户

  • 相关阅读:
    干翻Dubbo系列第十五篇:Rest协议基于SpringBoot的规范化开发
    共轭梯度法
    阿里云天池大赛赛题(机器学习)——阿里云安全恶意程序检测(完整代码)
    为什么你觉得FPGA难学?如何入门?
    SpringDataJpa源码理解
    重学设计模式(三、设计模式-策略模式)
    【iptables 实战】02 iptables常用命令
    【Java | 多线程】可重入锁的概念以及示例
    LabVIEW开发航天器模拟器的姿态控制和反作用轮动量管理
    【好书推荐】计算机考研精炼1000题——考研408不可或缺
  • 原文地址:https://blog.csdn.net/rygy_/article/details/127736638