[LeetCode] 2208. Minimum Operations to Halve Array Sum

发布时间 2023-07-25 01:28:02作者: CNoodle

You are given an array nums of positive integers. In one operation, you can choose any number from nums and reduce it to exactly half the number. (Note that you may choose this reduced number in future operations.)

Return the minimum number of operations to reduce the sum of nums by at least half.

Example 1:

Input: nums = [5,19,8,1]
Output: 3
Explanation: The initial sum of nums is equal to 5 + 19 + 8 + 1 = 33.
The following is one of the ways to reduce the sum by at least half:
Pick the number 19 and reduce it to 9.5.
Pick the number 9.5 and reduce it to 4.75.
Pick the number 8 and reduce it to 4.
The final array is [5, 4.75, 4, 1] with a total sum of 5 + 4.75 + 4 + 1 = 14.75. 
The sum of nums has been reduced by 33 - 14.75 = 18.25, which is at least half of the initial sum, 18.25 >= 33/2 = 16.5.
Overall, 3 operations were used so we return 3.
It can be shown that we cannot reduce the sum by at least half in less than 3 operations.

Example 2:

Input: nums = [3,8,20]
Output: 3
Explanation: The initial sum of nums is equal to 3 + 8 + 20 = 31.
The following is one of the ways to reduce the sum by at least half:
Pick the number 20 and reduce it to 10.
Pick the number 10 and reduce it to 5.
Pick the number 3 and reduce it to 1.5.
The final array is [1.5, 8, 5] with a total sum of 1.5 + 8 + 5 = 14.5. 
The sum of nums has been reduced by 31 - 14.5 = 16.5, which is at least half of the initial sum, 16.5 >= 31/2 = 15.5.
Overall, 3 operations were used so we return 3.
It can be shown that we cannot reduce the sum by at least half in less than 3 operations.

Constraints:

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

将数组和减半的最少操作次数。

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

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

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/minimum-operations-to-halve-array-sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路是贪心。我们用一个最大堆把 input 数组里的所有元素都存起来,然后按照题目定义的,每次弹出最大元素之后,将这个元素减半,再放回堆中。这期间一直用一个变量记录所有元素的总和,当总和小于原数组总和的一半,即停止操作。注意这里我们需要用 double,因为 int 型的除法精度不够。

时间O(nlogn)

空间O(n)

Java实现

 1 class Solution {
 2     public int halveArray(int[] nums) {
 3         double sum = 0;
 4         PriorityQueue<Double> queue = new PriorityQueue<>((a, b) -> Double.compare(b, a));
 5         for (int num : nums) {
 6             sum += (double) num;
 7             queue.offer((double) num);
 8         }
 9 
10         double target = sum / 2;
11         int steps = 0;
12         while (!queue.isEmpty() && sum > target) {
13             double cur = queue.poll();
14             sum -= cur;
15             queue.offer(cur / 2);
16             sum += cur / 2;
17             steps++;
18         }
19         return steps;
20     }
21 }

 

LeetCode 题目总结