🔗 🟡 2530. Maximal Score After Applying K Operations 1386

tags: Weekly Contest 327 陣列(Array) 貪心(Greedy) 堆積(Heap)

題意

給定一個下標從 00 開始的整數陣列 numsnums 和一個整數 kk。你的 起始分數00

在每次 操作 中:

  1. 選擇一個索引 ii 使得 0i<nums.length0 \leq i < nums.length
  2. 將你的 分數 增加 nums[i]nums[i],並且
  3. nums[i]nums[i] 替換為 nums[i]/3\lceil nums[i] / 3 \rceil

返回在 恰好 執行 kk 次操作後你能獲得的最大可能 分數

向上取整函數 val\lceil val \rceil 是不小於 valval 的最小整數。

約束條件

  • 1nums.length,k1051 \leq nums.length, k \leq 10^5
  • 1nums[i]1091 \leq nums[i] \leq 10^9

思路:貪心(Greedy) + 堆積(Heap)模擬

為了獲得最大可能分數,我們可以基於 貪心(Greedy) 思路,每次選擇當前陣列中最大的元素進行操作。

而為了快速獲取當前陣列中最大的元素,我們可以使用 堆積(Heap) ,透過維護一個 最大堆積(Max Heap) 使得我們可以快速獲取當前最大的元素。

在每次操作時,我們將當前最大的元素取出,並將其加入到總分中,然後將其替換為 x3\lceil \frac{x}{3} \rceil,並將其重新插入堆積中。

值得注意的是,由於 xx 為整數,因此 x3\lceil \frac{x}{3} \rceil 等價於 x+23\lfloor \frac{x + 2}{3} \rfloor,即 x+23\frac{x + 2}{3} 的整數部分。

此外,Python 中的 heapq 會維護一個最小堆積,因此我們需要將元素取反,以維護一個最大堆積。

複雜度分析

  • 時間複雜度:O(n+klogn)\mathcal{O}(n + k \log n),其中 nn 為陣列長度。
    • 初始化堆積需要 O(n)\mathcal{O}(n) 的時間複雜度。
    • 每次操作需要 O(logn)\mathcal{O}(\log n) 的時間複雜度,總共執行 kk 次。
  • 空間複雜度:O(n)\mathcal{O}(n),其中 nn 為陣列長度。
    • 需要額外的 O(n)\mathcal{O}(n) 空間來維護堆積。
1
2
3
4
5
6
7
8
9
10
11
class Solution:
def maxKelements(self, nums: List[int], k: int) -> int:
hp = [-x for x in nums]
heapify(hp)
ans = 0
for _ in range(k):
x = -heappop(hp)
ans += x
# heappush(hp, -math.ceil(x / 3))
heappush(hp, -((x + 2) // 3))
return ans
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Solution {
public:
long long maxKelements(vector<int>& nums, int k) {
priority_queue<int> hp(nums.begin(), nums.end());
long long ans = 0;
for (int i = 0; i < k; i++) {
int x = hp.top();
hp.pop();
ans += x;
// hp.push(ceil(x / 3.0));
hp.push((x + 2) / 3);
}
return ans;
}
};

寫在最後

Cover photo is remixed from @吃肥皂泡泡, thanks for their work!