【LeetCode 算法】Minimum Operations to Halve Array Sum 将数组和减半的最少操作次数-Greedy

文章目录

Minimum Operations to Halve Array Sum 将数组和减半的最少操作次数

问题描述:

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

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

1 < = n u m s . l e n g t h < = 1 0 5 1 < = n u m s i < = 1 0 7 1 <= nums.length <= 10^5\\ 1 <= numsi <= 10^7 1<=nums.length<=1051<=numsi<=107

分析

目标是将数组的和减少到原始数组和的一半,而且是最小的操作数。

一次操作可以选任意的元素减半 ,而且可以重复选择某个下标的元素。所以几乎不存在限制

也就是说一定在经过若干次操作后,可以达到目标

记原始数组和为 s u m sum sum,那么目标就是 h a l f = s u m / 2 half = sum/2 half=sum/2;

但是问题是要求最少的,所以细化一下目标,

  • 如果最后一次的操作使得最新的数组和 s ′ = = h a l f s'==half s′==half,说明这是最后一次操作,
  • 同样如果 s ′ < h a l f s'<half s′<half,也是说明最后一次操作。
  • 如果 s ′ > h a l f s'>half s′>half,说明还需要进行操作。

而且为了使得能够尽快 使 s ′ s' s′靠近到目标 h a l f half half,每次一定是选择当前数组中 的 m a x max max,进行操作。

暴力

如果是暴力的算法,就是每次选择最大 ,然后减半,放回去,再找一次最大,循环往复。

每次找数组的最大值时间复杂度 O ( N ) O(N) O(N),而且要达到目标需要操作N次,整体的时间复杂度为 O ( N 2 ) O(N^2) O(N2).

所以这个暴力的时间复杂度有TLE的风险。

优先队列

所以就需要进行加速,而唯一能选 的就是优先队列

在优先队列中的维护一个最大值或最小值 的平均时间复杂度是 O ( l o g N ) O(logN) O(logN),所以整体的时间复杂度就会降低到 O ( N l o g N ) O(NlogN) O(NlogN).

同时需要注意的是数据的范围 ,以及精度

代码

TLE

java 复制代码
public int halveArray(int[] nums) {
        Double tot = 0.0;
        int n = nums.length;
        Double[] arr = new Double[n];
        for(int i =0;i<n;i++){
            arr[i] = nums[i]*1.0;
            tot+= arr[i];
        }
        Double half = tot*0.5;
        int ans =0;
        for(int i =0;i<n;i++){
            if(half<=0) break;
            int id =0;
            double max = arr[id];
            for(int j =0;j<n;j++){
                if(arr[j]>max){
                    max = arr[j];
                    id = j;
                }
            }
            arr[id] *= 0.5;
            half -= arr[id];
            ans++;
        }
        return ans;
    }

时间复杂度 O ( N 2 ) O(N^2) O(N2)

空间复杂度 O ( 1 ) O(1) O(1)

优先队列

java 复制代码
public int halveArray(int[] nums) {
        PriorityQueue<Double> pq = new PriorityQueue<Double>((a,b)->{return b.compareTo(a);});
        Double tot = 0.0;
        for(int num: nums){
            Double t = num*1.0;
            tot+=t;
            pq.offer(t);
        }          
        Double half = tot*0.5;
        int ans =0;
        while(half>0&&!pq.isEmpty()){
            Double t = pq.poll();
            t *=0.5;
            half -= t;
            ans++;
            pq.offer(t);
        }
        return ans;
    }

时间复杂度 O ( N l o g N ) O(NlogN) O(NlogN)

空间复杂度 O ( N ) O(N) O(N)

Tag

Array

Greedy

Heap

相关推荐
rannn_1116 小时前
【力扣hot100】链表专题|160、206、234、141、142
java·算法·leetcode·链表·面试·开发
数模竞赛Paid answer6 小时前
2026年华东杯数学建模B题医药物流安排问题解题全过程文档及程序
算法·数学建模·数据分析·华东杯
不会代码的小猴6 小时前
21. 泛型编程上
开发语言·c++·笔记·算法
营养充电站7 小时前
VS Code Git 工作树:解锁多分支并行开发的高效体验
leetcode·决策树·逻辑回归·散列表·模拟退火算法
AI备案指南-满满7 小时前
大模型与算法备案全流程详解:从零到通过的完整指南
人工智能·算法·备案·大模型备案·算法备案
江畔柳前堤7 小时前
LLM 训练核心机制深度解析:Warmup、Cosine Decay 与 Perplexity 的完整知识体系
网络·人工智能·深度学习·算法·机器学习·语音识别
一只旭宝7 小时前
细讲C加加【9】C++ std::function与std::bind详解|仿函数、绑定器、类成员绑定、占位符、成员偏移指针
开发语言·c++·算法
良木林8 小时前
子串 - LeetCode hot 100
算法·leetcode·职场和发展
陌诺曦.8 小时前
Python扩展小练习
算法