題目描述
給你一個正整數數組 nums 。每一次操作中,你可以從 nums 中選擇 任意 一個數并將它減小到 恰好 一半。(注意,在后續(xù)操作中你可以對減半過的數繼續(xù)執(zhí)行操作)
請你返回將 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
思路
每次操作,會將數組中的一個數減半。要求使得數組和,至少減少到一半的操作次數最少是多少,那么每次操作應該選擇當前數組的最大值進行減半。
因此用一個優(yōu)先隊列(大根堆)維護數組中的所有數,每次從優(yōu)先隊列中取出最大值,將其減半,然后將減半后的數重新放入優(yōu)先隊列中,同時更新減半和的值和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的值小于數組和的一半那么執(zhí)行循環(huán)
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)。文章來源:http://www.zghlxwxcb.cn/news/detail-604251.html
測試結果
文章來源地址http://www.zghlxwxcb.cn/news/detail-604251.html
到了這里,關于將數組和減半的最少操作次數(力扣)的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!