|
| 1 | +--- |
| 2 | +title: 2530.执行 K 次操作后的最大分数 |
| 3 | +date: 2023-10-18 09:32:49 |
| 4 | +tags: [题解, LeetCode, 中等, 贪心, 数组, 堆(优先队列), 堆, 优先队列] |
| 5 | +--- |
| 6 | + |
| 7 | +# 【LetMeFly】2530.执行 K 次操作后的最大分数:优先队列(贪心) |
| 8 | + |
| 9 | +力扣题目链接:[https://leetcode.cn/problems/maximal-score-after-applying-k-operations/](https://leetcode.cn/problems/maximal-score-after-applying-k-operations/) |
| 10 | + |
| 11 | +<p>给你一个下标从 <strong>0</strong> 开始的整数数组 <code>nums</code> 和一个整数 <code>k</code> 。你的 <strong>起始分数</strong> 为 <code>0</code> 。</p> |
| 12 | + |
| 13 | +<p>在一步 <strong>操作</strong> 中:</p> |
| 14 | + |
| 15 | +<ol> |
| 16 | + <li>选出一个满足 <code>0 <= i < nums.length</code> 的下标 <code>i</code> ,</li> |
| 17 | + <li>将你的 <strong>分数</strong> 增加 <code>nums[i]</code> ,并且</li> |
| 18 | + <li>将 <code>nums[i]</code> 替换为 <code>ceil(nums[i] / 3)</code> 。</li> |
| 19 | +</ol> |
| 20 | + |
| 21 | +<p>返回在 <strong>恰好</strong> 执行 <code>k</code> 次操作后,你可能获得的最大分数。</p> |
| 22 | + |
| 23 | +<p>向上取整函数 <code>ceil(val)</code> 的结果是大于或等于 <code>val</code> 的最小整数。</p> |
| 24 | + |
| 25 | +<p> </p> |
| 26 | + |
| 27 | +<p><strong>示例 1:</strong></p> |
| 28 | + |
| 29 | +<pre> |
| 30 | +<strong>输入:</strong>nums = [10,10,10,10,10], k = 5 |
| 31 | +<strong>输出:</strong>50 |
| 32 | +<strong>解释:</strong>对数组中每个元素执行一次操作。最后分数是 10 + 10 + 10 + 10 + 10 = 50 。 |
| 33 | +</pre> |
| 34 | + |
| 35 | +<p><strong>示例 2:</strong></p> |
| 36 | + |
| 37 | +<pre> |
| 38 | +<strong>输入:</strong>nums = [1,10,3,3,3], k = 3 |
| 39 | +<strong>输出:</strong>17 |
| 40 | +<strong>解释:</strong>可以执行下述操作: |
| 41 | +第 1 步操作:选中 i = 1 ,nums 变为 [1,<em><strong>4</strong></em>,3,3,3] 。分数增加 10 。 |
| 42 | +第 2 步操作:选中 i = 1 ,nums 变为 [1,<em><strong>2</strong></em>,3,3,3] 。分数增加 4 。 |
| 43 | +第 3 步操作:选中 i = 2 ,nums 变为 [1,1,<em><strong>1</strong></em>,3,3] 。分数增加 3 。 |
| 44 | +最后分数是 10 + 4 + 3 = 17 。 |
| 45 | +</pre> |
| 46 | + |
| 47 | +<p> </p> |
| 48 | + |
| 49 | +<p><strong>提示:</strong></p> |
| 50 | + |
| 51 | +<ul> |
| 52 | + <li><code>1 <= nums.length, k <= 10<sup>5</sup></code></li> |
| 53 | + <li><code>1 <= nums[i] <= 10<sup>9</sup></code></li> |
| 54 | +</ul> |
| 55 | + |
| 56 | + |
| 57 | + |
| 58 | +## 方法一:优先队列(贪心) |
| 59 | + |
| 60 | +每次取一个数并累加到总分中,要想使总分最大,当然要选尽可能大的数。 |
| 61 | + |
| 62 | +因此使用一个大根堆,将数组中所有的整数加入堆栈(优先队列),并进行$k$次以下操作: |
| 63 | + |
| 64 | +> 每次从队首(堆顶)取出一个元素累加,并将其三分之一(向上取整)重新入队。 |
| 65 | +
|
| 66 | +最终返回累加的答案即可。 |
| 67 | + |
| 68 | ++ 时间复杂度$O(len(nums) + k\times \log len(nums))$ |
| 69 | ++ 空间复杂度$O(len(nums))$ |
| 70 | + |
| 71 | +### AC代码 |
| 72 | + |
| 73 | +#### C++ |
| 74 | + |
| 75 | +```cpp |
| 76 | +typedef long long ll; |
| 77 | +class Solution { |
| 78 | +public: |
| 79 | + ll maxKelements(vector<int>& nums, int k) { |
| 80 | + priority_queue<int> pq; |
| 81 | + for (int t : nums) { |
| 82 | + pq.push(t); |
| 83 | + } |
| 84 | + ll ans = 0; |
| 85 | + while (k--) { |
| 86 | + int thisNum = pq.top(); |
| 87 | + pq.pop(); |
| 88 | + ans += thisNum; |
| 89 | + pq.push((thisNum + 2) / 3); |
| 90 | + } |
| 91 | + return ans; |
| 92 | + } |
| 93 | +}; |
| 94 | +``` |
| 95 | +
|
| 96 | +#### Python |
| 97 | +
|
| 98 | +```python |
| 99 | +# from typing import List |
| 100 | +# import heapq |
| 101 | +
|
| 102 | +class Solution: |
| 103 | + def maxKelements(self, nums: List[int], k: int) -> int: |
| 104 | + nums = list(map(lambda x: -x, nums)) |
| 105 | + heapq.heapify(nums) |
| 106 | + ans = 0 |
| 107 | + for _ in range(k): |
| 108 | + thisNum = -heapq.heappop(nums) |
| 109 | + ans += thisNum |
| 110 | + heapq.heappush(nums, -((thisNum + 2) // 3)) |
| 111 | + return ans |
| 112 | +``` |
| 113 | + |
| 114 | +> 同步发文于CSDN,原创不易,转载经作者同意后请附上[原文链接](https://blog.tisfy.eu.org/2023/10/18/LeetCode%202530.%E6%89%A7%E8%A1%8CK%E6%AC%A1%E6%93%8D%E4%BD%9C%E5%90%8E%E7%9A%84%E6%9C%80%E5%A4%A7%E5%88%86%E6%95%B0/)哦~ |
| 115 | +> Tisfy:[https://letmefly.blog.csdn.net/article/details/133899145](https://letmefly.blog.csdn.net/article/details/133899145) |
0 commit comments