2530. 执行 K 次操作后的最大分数

这篇具有很好参考价值的文章主要介绍了2530. 执行 K 次操作后的最大分数。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

2530. 执行 K 次操作后的最大分数,LeetCode的秃头之路,算法,leetcode,优先队列,力扣


2530. 执行 K 次操作后的最大分数
难度: 中等
来源: 每日一题 2023.10.18

给你一个下标从 0 开始的整数数组 nums 和一个整数 k 。你的 起始分数0

在一步 操作 中:

选出一个满足 0 <= i < nums.length 的下标 i
将你的 分数 增加 nums[i] ,并且
nums[i] 替换为 ceil(nums[i] / 3)
返回在 恰好 执行 k 次操作后,你可能获得的最大分数。

向上取整函数 ceil(val) 的结果是大于或等于 val 的最小整数。

示例 1:

输入:nums = [10,10,10,10,10], k = 5
输出:50
解释:对数组中每个元素执行一次操作。最后分数是 10 + 10 + 10 + 10 + 10 = 50 。

示例 2:

输入:nums = [1,10,3,3,3], k = 3
输出:17
解释:可以执行下述操作:
第 1 步操作:选中 i = 1 ,nums 变为 [1,4,3,3,3] 。分数增加 10 。
第 2 步操作:选中 i = 1 ,nums 变为 [1,2,3,3,3] 。分数增加 4 。
第 3 步操作:选中 i = 2 ,nums 变为 [1,1,1,3,3] 。分数增加 3 。
最后分数是 10 + 4 + 3 = 17 。

提示:

  • 1 <= nums.length, k <= 10^5
  • 1 <= nums[i] <= 10^9
class Solution {
    public long maxKelements(int[] nums, int k) {

    }
}

分析与题解

  • 暴力求解 时间超时, 失败

    直接暴力法就是我们按照题意进行模拟运行, 每一次取完数组中的最后一个值就根据题意更新这个值, 然后重新排序整个数组.

    long result = 0;
    for(int i = 0; i < k; i++) {
        int num = nums[nums.length - 1];
        result += num;
        num = num/3 + (num%3 > 0 ? 1 : 0);
        nums[nums.length - 1] = num;
        Arrays.sort(nums);
    }
    

    整体的解题思路如下所示.

    class Solution {
        public long maxKelements(int[] nums, int k) {
            Arrays.sort(nums);
            long result = 0;
            for(int i = 0; i < k; i++) {
                int num = nums[nums.length - 1];
                result += num;
                num = num/3 + (num%3 > 0 ? 1 : 0);
                nums[nums.length - 1] = num;
                Arrays.sort(nums);
            }
            return result;
        }
    }
    

    复杂度分析:

    • 时间复杂度: O(klogn), 时间复杂度与k相关, 排序需要损耗的时间复杂度为 logn
    • 空间复杂度: O(klogn), 需要 k 次排序, 每一次都要消耗的空间复杂度为 logn

    结果如下所示.

    2530. 执行 K 次操作后的最大分数,LeetCode的秃头之路,算法,leetcode,优先队列,力扣


  • 额外数组法

    既然暴力排序的方式时间超时, 其原因就在于Arrays.sort(nums);, 那我们就找一个不用排序的方式.

    我们发现, 当我们对 nums 排序完成之后, 然后取出最后一位数据时, 并进行 ceil(nums[i] / 3), 生成许多的 item, 一定有这样的规律: 先生成的 item 一定不小于后生成的 item 的值.

    比如 [1, 10, 3, 3, 3] 第一次是 ceil(10 / 3) = 4, 第二次是 ceil(4 / 3) = 2, 第三次是 ceil(3 / 3) = 1, 结果是 4 > 2 > 1, 结论是成立的.

    我们把这些 ceil(nums[i] / 3) 生成的 item 单独并且依次放在一个数组removeNums中, 那么这个数组removeNums也是有序的.

    由于 nums 不再删除数据了, 所以我们要用一个 index 记录当前 nums 中能取到的最大值.

    这时候取值过程就要分不同的逻辑分支了.

    • removeNums 没有数据时, 我们就从 nums 中取最大值. 同时, index也需要偏移. 并且把 ceil(nums[i] / 3) 添加到 removeNums 中.

      2530. 执行 K 次操作后的最大分数,LeetCode的秃头之路,算法,leetcode,优先队列,力扣

      int num = nums[numsIndex];
      result += num;
      removeNums.add(num/3 + (num%3 > 0 ? 1 : 0));
      numsIndex--;
      
    • removeNums 有数据时, 我们就从 nums 中取最大值 和 从 removeNums 中取最大值, 两者取较大值. 当然了这时候还是需要更新 removeNums 的数据(删除最大值, 计算后放入数组尾部).

      2530. 执行 K 次操作后的最大分数,LeetCode的秃头之路,算法,leetcode,优先队列,力扣

      int num = removeNums.get(0);
      removeNums.remove(0);
      result += num;
      removeNums.add(num/3 + (num%3 > 0 ? 1 : 0));
      

    接下来, 我们就一起看一下按照这个思路的整体的解题过程.

    class Solution {
        public long maxKelements(int[] nums, int k) {
            Arrays.sort(nums);
            long result = 0;
            ArrayList<Integer> removeNums = new ArrayList<>();
            int numsIndex = nums.length - 1;
            for(int i = 0; i < k; i++) {
                // 条件1: 如果 numsIndex 小于等于0
                // 条件2: 如果当前removeNums有数据, 并且当前的removeNums的数据大于nums[numsIndex], 那就从removeNums中取出数据
                // numsIndex 下标大于等于0是边界条件
                if( numsIndex < 0 || (removeNums.size() != 0 && removeNums.get(0) > nums[numsIndex])) {
                    int num = removeNums.get(0);
                    removeNums.remove(0);
                    result += num;
                    removeNums.add(num/3 + (num%3 > 0 ? 1 : 0));
                } else {
                    int num = nums[numsIndex];
                    result += num;
                    removeNums.add(num/3 + (num%3 > 0 ? 1 : 0));
                    numsIndex--;
                }
            }
            return result;
        }
    }
    

    复杂度分析:

    • 时间复杂度: O(k + logn), 遍历时间复杂度与k相关, 排序需要损耗的时间复杂度为 logn
    • 空间复杂度: O(logn), 排序消耗的空间复杂度为 logn

    结果如下所示.

    2530. 执行 K 次操作后的最大分数,LeetCode的秃头之路,算法,leetcode,优先队列,力扣


  • 优先队列法

    直接使用Java内置的优先队列 PriorityQueue, 这种方式我们不需要管理内部的排序逻辑, 直接通过 PriorityQueue来完成.

    首先就是把所有的数据添加到优先队列中.

    PriorityQueue<Integer> q = new PriorityQueue<Integer>((a, b) -> b - a);
    for (int num : nums) {
        q.offer(num);
    }
    

    然后就是通过 poll() 取出最大值, 然后计算后再添加到优先队列中.

    long ans = 0;
    for (int i = 0; i < k; ++i) {
        int num = q.poll();
        ans += num;
        q.offer(num/3 + (num%3 > 0 ? 1 : 0));
    }
    

    接下来, 我们一起看一下整体的代码逻辑.

    class Solution {
        public long maxKelements(int[] nums, int k) {
            PriorityQueue<Integer> q = new PriorityQueue<Integer>((a, b) -> b - a);
            for (int num : nums) {
                q.offer(num);
            }
            long ans = 0;
            for (int i = 0; i < k; ++i) {
                int num = q.poll();
                ans += num;
                q.offer(num/3 + (num%3 > 0 ? 1 : 0));
            }
            return ans;
        }
    }
    

    复杂度分析:

    • 时间复杂度: O(nk), 遍历时间复杂度与k nums的长度 相关
    • 空间复杂度: O(n), 优先队列消耗的空间复杂度为 O(n)

    结果如下所示.

    2530. 执行 K 次操作后的最大分数,LeetCode的秃头之路,算法,leetcode,优先队列,力扣文章来源地址https://www.toymoban.com/news/detail-723991.html

到了这里,关于2530. 执行 K 次操作后的最大分数的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • C++深度优先搜索的应用:在树上执行操作以后得到的最大分数

    深度优先搜索(DFS) 有一棵 n 个节点的无向树,节点编号为 0 到 n - 1 ,根节点编号为 0 。给你一个长度为 n - 1 的二维整数数组 edges 表示这棵树,其中 edges[i] = [ai, bi] 表示树中节点 ai 和 bi 有一条边。 同时给你一个长度为 n 下标从 0 开始的整数数组 values ,其中 values[i] 表示第

    2024年02月05日
    浏览(43)
  • leetcode:2011. 执行操作后的变量值(python3解法)

    存在一种仅支持 4 种操作和 1 个变量  X  的编程语言: ++X  和  X++  使变量  X  的值  加   1 --X  和  X--  使变量  X  的值  减   1 最初, X  的值是  0 给你一个字符串数组  operations  ,这是由操作组成的一个列表,返回执行所有操作后,   X  的  最终值  。 示例 1:

    2024年02月11日
    浏览(40)
  • LeetCode、2542. 最大子序列的分数【中等,排序+小顶堆】

    博主介绍:✌目前全网粉丝2W+,csdn博客专家、Java领域优质创作者,博客之星、阿里云平台优质作者、专注于Java后端技术领域。 涵盖技术内容:Java后端、算法、分布式微服务、中间件、前端、运维、ROS等。 博主所有博客文件目录索引:博客目录索引(持续更新) 视频平台:

    2024年01月18日
    浏览(41)
  • 2317.操作后的最大异或和

    首先num[i]^x可以知道 这里可以变成任意一个数字 又有num[i]上上面的数字 所以我们可以扣掉任意位的1把它变成0 答案让我们求异或和 所以只要这一位有1 答案的这一位就有1 我们发现这就是一个按位或运算

    2024年02月08日
    浏览(59)
  • 【刷题之路Ⅲ】LeetCode 827. 最大人工岛

    读完题目我们会发现,这道题正来做其实是很难的,那我们就反着做。 我们可以将思路转化为由数字是0的格子出发,统计与它相邻的岛屿的面积,依次遍历完所有的0格子,就能得到最大的面积了: 统计面积的操作使用bfs来做,但是如果直接这样做我们会发现,存在许多的重

    2024年01月18日
    浏览(27)
  • 2734. 执行子串操作后的字典序最小字符串

    给你一个仅由小写英文字母组成的字符串 s 。在一步操作中,你可以完成以下行为: 选则 s 的任一非空子字符串,可能是整个字符串,接着将字符串中的每一个字符替换为英文字母表中的前一个字符。例如,\\\'b\\\' 用 \\\'a\\\' 替换,\\\'a\\\' 用 \\\'z\\\' 替换。 返回执行上述操作 恰好一次 后可以

    2024年02月09日
    浏览(39)
  • 一道神奇的面试题---无序数组排序后的最大相邻差

    一:概述 这个算法的面试题目是:有一个无序整型数组,如何求出该数组排序后的任意两个相邻元素的最大差值?要求时间和空间复杂度尽可能低。     二:具体说明 1第一种解法(初步解法) 这个解法的大致思路:使用任意一种时间复杂度为O(nlogn)的排序算法(如快速排序)给

    2024年04月28日
    浏览(36)
  • Linux误执行chmod -R 777 / 后的成功挽救方法

    在Linux环境上给文件夹赋权的时候,误执行了 chmod -R 777 / ,并且退出了连接窗口,再尝试远程登录服务器时,发现登录不上去了。排查服务器是否挂掉,没有,在网页上可以正常访问部署在上面的项目;最后发现是ssh连接挂掉了,百度了很多看到需要格式化啊、重新备份数据

    2024年02月11日
    浏览(36)
  • leetcode做题笔记172. 阶乘后的零

    给定一个整数  n  ,返回  n!  结果中尾随零的数量。 提示  n! = n * (n - 1) * (n - 2) * ... * 3 * 2 * 1 示例 1: 示例 2: 示例 3: c语言解法 由题可知:每5个数则末尾会多一个零,因为:5乘任何带以二为因数的数尾部均会添加一个零,利用这个特点题目要求的问题可转化为找给出

    2024年02月07日
    浏览(43)
  • leetcode1475. 商品折扣后的最终价格 【单调栈】

    简单题 第一次错误做法 运行结果: 错误分析:入栈的是元素,如果之后出现相等的元素,则会覆盖哈希表中的值。 正确思路: 修改入栈元素为下标之后: for遍历数组元素写法:  为什么运行时间变长了?

    2024年02月11日
    浏览(39)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包