将数组和减半的最少操作次数(力扣)

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

题目描述

给你一个正整数数组 nums 。每一次操作中,你可以从 nums 中选择 任意 一个数并将它减小到 恰好 一半。(注意,在后续操作中你可以对减半过的数继续执行操作)

请你返回将 nums 数组和 至少 减少一半的 最少 操作数。

示例 1:

输入:nums = [5,19,8,1]
输出:3
解释:初始 nums 的和为 5 + 19 + 8 + 1 = 33 。
以下是将数组和减少至少一半的一种方法:
选择数字 19 并减小为 9.5 。
选择数字 9.5 并减小为 4.75 。
选择数字 8 并减小为 4 。
最终数组为 [5, 4.75, 4, 1] ,和为 5 + 4.75 + 4 + 1 = 14.75 。
nums 的和减小了 33 - 14.75 = 18.25 ,减小的部分超过了初始数组和的一半,18.25 >= 33/2 = 16.5 。
我们需要 3 个操作实现题目要求,所以返回 3 。
可以证明,无法通过少于 3 个操作使数组和减少至少一半。

示例 2:

输入:nums = [3,8,20]
输出:3
解释:初始 nums 的和为 3 + 8 + 20 = 31 。
以下是将数组和减少至少一半的一种方法:
选择数字 20 并减小为 10 。
选择数字 10 并减小为 5 。
选择数字 3 并减小为 1.5 。
最终数组为 [1.5, 8, 5] ,和为 1.5 + 8 + 5 = 14.5 。
nums 的和减小了 31 - 14.5 = 16.5 ,减小的部分超过了初始数组和的一半, 16.5 >= 31/2 = 16.5 。
我们需要 3 个操作实现题目要求,所以返回 3 。
可以证明,无法通过少于 3 个操作使数组和减少至少一半。
提示:

1 <= nums.length <= 105
1 <= nums[i] <= 107

思路

每次操作,会将数组中的一个数减半。要求使得数组和,至少减少到一半的操作次数最少是多少,那么每次操作应该选择当前数组的最大值进行减半。
因此用一个优先队列(大根堆)维护数组中的所有数,每次从优先队列中取出最大值,将其减半,然后将减半后的数重新放入优先队列中,同时更新减半和的值和temp,直到temp大于等于数组和sum的一半为止。返回操作次数即可。

测试代码


class Solution{
    public int halveArray(int[] nums) {
        PriorityQueue<Double> p=new PriorityQueue(new Comparator<Double>() {
            @Override
            public int compare(Double o1, Double o2) {
                //排序,大的数字排在前面
                return o2-o1>0?1:o2-o1<0?-1:0;
            }
        });

        //往队列添加nums数组的值,并计算数组的和
        double sum=0;
        for (double i:nums) {
            p.offer(i*1.0);
            sum+=i;
        }

        int count=0;
        double temp=0;
        //如果temp的值小于数组和的一半那么执行循环
        while (sum/2.0>temp){
            //删除堆顶元素
            double t=(double)p.poll();
            temp+=t/2;
            //添加减少一半的数值
            p.add(t/2);
            count++;
        }
        //返回操作次数
        return count;
    }
}

复杂度

将元素插入堆和删除堆顶元素的时间复杂度为O(logN),其中N是元素的数量。因此,堆操作的总时间复杂度为O(NlogN)。
堆可能包含所有的数组元素,因此空间复杂度为O(N)。

测试结果

将数组和减半的最少操作次数(力扣),leetcode题目,leetcode,算法,数据结构文章来源地址https://www.toymoban.com/news/detail-604251.html

到了这里,关于将数组和减半的最少操作次数(力扣)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • 【LeetCode】1654:到家的最少跳跃次数的解题思路 & 关于力扣无法return的BUG的讨论

    有一只跳蚤的家在数轴上的位置 x 处。请你帮助它从位置 0 出发,到达它的家。 跳蚤跳跃的规则如下: 它可以 往前 跳恰好 a 个位置(即往右跳)。 它可以 往后 跳恰好 b 个位置(即往左跳)。 它不能 连续 往后跳 2 次。 它不能跳到任何 forbidden 数组中的位置。 跳蚤可以往

    2024年02月10日
    浏览(49)
  • 【算法】力扣【动态规划,LCS】1312. 让字符串成为回文串的最少插入次数

    1312. 让字符串成为回文串的最少插入次数 本文探讨的是力扣(LeetCode)上的第1312题:让字符串成为回文串的最少插入次数。这是一道属于动态规划类别下的困难题目,通常以回文串相关的操作来衡量算法的优化和执行效率。 问题的核心是给定一个字符串 s ,你可以在任意位

    2024年01月23日
    浏览(50)
  • Leetcode3071. 在矩阵上写出字母 Y 所需的最少操作次数

    题目来源:3071. 在矩阵上写出字母 Y 所需的最少操作次数 统计 Y 中的元素出现次数,记到一个长为 3 的数组 cnt1 中。统计不在 Y 中的元素出现次数,记到一个长为 3 的数组 cnt2 中。 计算最多可以保留多少个元素不变,设这个值为 maxNotChange。 在 0,1,2 中枚举 i 和 j,其中 i≠

    2024年03月18日
    浏览(47)
  • C++二分算法:得到子序列的最少操作次数

    二分查找算法合集 给你一个数组 target ,包含若干 互不相同 的整数,以及另一个整数数组 arr ,arr 可能 包含重复元素。 每一次操作中,你可以在 arr 的任意位置插入任一整数。比方说,如果 arr = [1,4,1,2] ,那么你可以在中间添加 3 得到 [1,4,3,1,2] 。你可以在数组最开始或最后

    2024年02月05日
    浏览(45)
  • 【算法|动态规划No.28】leetcode1312. 让字符串成为回文串的最少插入次数

    个人主页:兜里有颗棉花糖 欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 兜里有颗棉花糖 原创 收录于专栏【手撕算法系列专栏】【LeetCode】 🍔本专栏旨在提高自己算法能力的同时,记录一下自己的学习过程,希望对大家有所帮助 🍓希望我们一起努力、成长,共同进步。

    2024年02月06日
    浏览(56)
  • 【LeetCode - 每日一题】1654. 到家的最少跳跃次数(23.08.30)

    可以左跳可以右跳 不能连续左跳两次 不能跳到负数 不能跳到 forbidden[] 求可以跳到 x 的最少跳跃次数 a. overview 最初时,只有 0 位置可以进行跳跃;在跳到 a 位置后,又可以跳到 2a 位置和 a-b 位置(如果 ab );然后又多了两个位置(或者一个位置)可以跳跃…因此这是一个

    2024年02月10日
    浏览(46)
  • 2023-06-17 LeetCode每日一题(分割圆的最少切割次数)

    点击跳转到题目位置 圆内一个 有效切割 ,符合以下二者之一: 该切割是两个端点在圆上的线段,且该线段经过圆心。 该切割是一端在圆心另一端在圆上的线段。 一些有效和无效的切割如下图所示。 给你一个整数 n ,请你返回将圆切割成相等的 n 等分的 最少 切割次数。

    2024年02月09日
    浏览(52)
  • 【LeetCode每日一题合集】2023.8.28-2023.9.3(到家的最少跳跃次数)

    https://leetcode.cn/problems/insert-interval/ 提示: 0 = intervals.length = 10^4 intervals[i].length == 2 0 = intervals[i][0] = intervals[i][1] = 10^5 intervals 根据 intervals[i][0] 按 升序 排列 newInterval.length == 2 0 = newInterval[0] = newInterval[1] = 10^5 当前区间与要加入的新区间之间的关系只有两种可能:相交或者不相

    2024年02月09日
    浏览(62)
  • LeetCode面试算法-力扣 88. 合并两个有序数组

    88. 合并两个有序数组 题目描述     给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。请你 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。 注意: 最终,合并后数组不应由函数返回,而是存储

    2024年02月10日
    浏览(48)
  • 力扣(LeetCode)算法_C++—— 两个数组的交集

    给定两个数组 nums1 和 nums2 ,返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。 示例 1: 输入:nums1 = [1,2,2,1], nums2 = [2,2] 输出:[2] 示例 2: 输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4] 输出:[9,4] 解释:[4,9] 也是可通过的

    2024年02月09日
    浏览(35)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包