Every day a Leetcode
题目来源:3266. K 次乘运算后的最终数组 II
解法1:3266. K 次乘运算后的最终数组 II
用最小堆手动模拟操作,直到原数组的最大值 mx 成为这 n 个数的最小值。
设此时还剩下 k 次操作,那么:
- 对于前 k mod n 小的数,还可以再操作 k/n+1 次。
- 其余元素,还可以再操作 k/n 次。
用快速幂计算操作这么多次后的结果。
代码:
/*
* @lc app=leetcode.cn id=3266 lang=cpp
*
* [3266] K 次乘运算后的最终数组 II
*/
// @lc code=start
class Solution
{
private:
const int MOD = 1e9 + 7;
// 快速幂
long long pow(long long x, int n)
{
long long res = 1;
for (; n; n /= 2)
{
if (n % 2)
res = res * x % MOD;
x = x * x % MOD;
}
return res;
}
public:
vector<int> getFinalState(vector<int> &nums, int k, int multiplier)
{
// 特判
if (multiplier == 1)
return move(nums);
int n = nums.size();
int mx = *max_element(nums.begin(), nums.end());
vector<pair<long long, int>> h(n);
for (int i = 0; i < n; i++)
{
h[i] = {nums[i], i};
}
ranges::make_heap(h, greater<>()); // 最小堆,O(n) 堆化
// 模拟,直到堆顶是 mx
for (; k && h[0].first < mx; k--)
{
ranges::pop_heap(h, greater<>());
h.back().first *= multiplier;
ranges::push_heap(h, greater<>());
}
// 剩余的操作可以直接用公式计算
ranges::sort(h);
for (int i = 0; i < n; i++)
{
auto &[x, j] = h[i];
nums[j] = x % MOD * pow(multiplier, k / n + (i < k % n)) % MOD;
}
return move(nums);
}
};
// @lc code=end
结果:
复杂度分析:
时间复杂度:O(n * logn * logmU),其中 n 是数组 nums 的长度,U=max(nums),m=multiplier。
空间复杂度:O(n),其中 n 是数组 nums 的长度。