leetcode 3266. K 次乘运算后的最终数组 II

3266. K 次乘运算后的最终数组 II

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

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

  • 找到 nums 中的 最小 值 x ,如果存在多个最小值,选择最 前面 的一个。
  • 将 x 替换为 x * multiplier 。

k 次操作以后,你需要将 nums 中每一个数值对 109 + 7 取余。

请你返回执行完 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]
取余操作后 [8, 4, 6, 5, 6]

示例 2:

输入:nums = [100000,2000], k = 2, multiplier = 1000000

输出:[999999307,999999993]

解释:

操作结果
1 次操作后 [100000, 2000000000]
2 次操作后 [100000000000, 2000000000]
取余操作后 [999999307, 999999993]

 

提示:

  • 1 <= nums.length <= 104
  • 1 <= nums[i] <= 109
  • 1 <= k <= 109
  • 1 <= multiplier <= 106

 

解题思路

快速幂
因为和坐标有关系,先定义以下变量
设置了一个node节点来存储元素的值value和对应的坐标index
获取最大值max
数组的长度length
这道题可以分以下思路
1.先把节点排序,在不超过最大值的情况下,和操作次数不超过k的情况下,用优先队列直接操作。复杂度不会超过32 * length。
2.当前的数组中,因为每一个元素 value * m >= max, 所以可以这么说,当操作 length 次的时候,就会是每个数字都会被操作一次.
可以用反证法来证明,若是不是每个数字都会被操作一次,那肯定是最大值没有操作, 但是每个值 value * m >= max 所以,操作 length - 1次的时候,所有的值,都比max大了,那么,max一定能被操作。
3.剩下的次数k中, 就会分为两部分,分别对length取商得到t1,对length取模得到t2
4.对于t2的操作,因为会小于length, 所以可以和步骤一 一样操作。
5.对于t1的操作,根据步骤二的理论,就相当于每个元素都会 * t1, 所以可以用快速幂来解答。

    public int[] getFinalState(int[] nums, int k, int m) {
        if (m == 1) {
            return nums;
        }
        int length = nums.length;
        Node[] nodes = new Node[length];
        int max = 0;
        for (int i = 0; i < length; i++) {
            nodes[i] = new Node(nums[i], i);
            max = Math.max(max, nums[i]);
        }
        int v = getList(nodes, k, m, max);
        if (v == k) {
            for (Node node : nodes) {
                nums[node.index] = (int) (node.value % 1000000007);
            }
            return nums;
        }
        k -= v;
        int t1 = k / length;
        int t2 = k % length;
        getList(nodes, t2, m);

        int mm = mm(m, t1);
//        System.out.println(v + "  " + t1 + "  " + t2 + "  " + mm);
        for (Node node : nodes) {
            nums[node.index] = (int) (node.value * mm % 1000000007);
        }
        return nums;
    }

    public int mm(int m, int t1) {
        long item = m;
        long sum = 1;
        while (t1 != 0) {
            if ((t1 & 1) == 1) {
                sum = sum * item % 1000000007;
            }
            item = item * item % 1000000007;
            t1 >>= 1;
        }
        return (int) sum;
    }

    private int getList(Node[] nodes, int k, int m, int max) {
        int count = 0;
        PriorityQueue<Node> queue = new PriorityQueue<>((a, b) -> a.value == b.value ? Integer.compare(a.index, b.index) : Long.compare(a.value, b.value));
        Collections.addAll(queue, nodes);
        while (queue.peek().value * m <= max) {
            Node poll = queue.poll();
            poll.value = poll.value * m ;
            queue.add(poll);
            count++;
            if (count == k) {
                break;
            }
        }
        return count;
    }

    private void getList(Node[] nodes, int k, int m) {
        int count = 0;
        PriorityQueue<Node> queue = new PriorityQueue<>((a, b) -> a.value == b.value ? Integer.compare(a.index, b.index) : Long.compare(a.value, b.value));
        Collections.addAll(queue, nodes);
        while (count < k) {
            Node poll = queue.poll();
            poll.value = poll.value * m ;
            queue.add(poll);
            count++;
        }
        for (Node node : nodes) {
            node.value = node.value % 1000000007;
        }
    }

    private static class Node {
        private long value;
        private int index;

        public Node(long value, int index) {
            this.value = value;
            this.index = index;
        }
    }

  

 

posted @ 2024-12-06 17:36  旺仔古李  阅读(8)  评论(0编辑  收藏  举报