LeetCode 3264.K次乘运算后的最终数组I

给你一个整数数组 nums ,一个整数 k 和一个整数 multiplier 。

你需要对 nums 执行 k 次操作,每次操作中:

找到 nums 中的 最小 值 x ,如果存在多个最小值,选择最 前面 的一个。

将 x 替换为 x * multiplier 。

请你返回执行完 k 次乘运算之后,最终的 nums 数组。

示例 1:

输入:nums = 2,1,3,5,6, k = 5, multiplier = 2

输出:8,4,6,5,6

解释:

操作 结果

1 次操作后 2, 2, 3, 5, 6

2 次操作后 4, 2, 3, 5, 6

3 次操作后 4, 4, 3, 5, 6

4 次操作后 4, 4, 6, 5, 6

5 次操作后 8, 4, 6, 5, 6

示例 2:

输入:nums = 1,2, k = 3, multiplier = 4

输出:16,8

解释:

操作 结果

1 次操作后 4, 2

2 次操作后 4, 8

3 次操作后 16, 8

提示:

1 <= nums.length <= 100

1 <= numsi <= 100

1 <= k <= 10

1 <= multiplier <= 5

对于两个数字x和y,假设x<y,且x * multiplier > y,那么两个进行乘算的顺序是一直重复的x、y、x、y、x...,因为x * multiplier > y后,下一步就是x * multiplier < y * multiplier。对于多个数字,也是同样的重复,我们可以先进行一轮乘算,直到原数组中的最大值变为最小值,然后再乘算一次,之后就都是重复操作了,如果此时还剩下k次操作,那么剩下每个元素至少会执行k/nums.size()次乘算,而且前k%nums.size()个元素还会进行更多的一次乘算,这可以用快速幂来计算:

cpp 复制代码
class Solution {
public:
    vector<int> getFinalState(vector<int>& nums, int k, int multiplier) {
        // O(n)空间
        vector<pair<int, int>> h;
        // O(n)时间
        for (int i = 0; i < nums.size(); ++i) {
            h.push_back({nums[i], i});
        }
        // 堆化,O(n)时间
        make_heap(h.begin(), h.end(), greater<>());

        // 先进行一轮乘算
        int mx = ranges::max(nums);
        // 如果数组中最大值为U,m为multiplier,对于该最大值需要循环以m为底U的对数次
        // 数组中最差有O(n)个最大值
        while (h[0].first <= mx && k > 0) {
            // O(logn)时间
            pop_heap(h.begin(), h.end(), greater<>());
            h.back().first *= multiplier;
            push_heap(h.begin(), h.end(), greater<>());

            --k;
        }

        sort(h.begin(), h.end());
        for (int i = 0; i < nums.size(); ++i) {
            auto &[v, j] = h[i];
            
            int repeatNum = k / nums.size();
            if (i < (k % nums.size())) {
                ++repeatNum;
            }
            nums[j] = v * pow(multiplier, repeatNum);
        }

        return nums;
    }

    int pow(long long num, int n) {
        int ans = 1;
        while (n) {
            if (n & 1) {
                ans *= num;
            }

            num *= num;
            n >>= 1;
        }

        return ans;
    }
};

如果nums的大小为n,数组中最大值为U,multiplier为m,则此算法时间复杂度为O(nlognlogm_{m}mU),空间复杂度为O(n)。