LeetCode 3264: Final Array State After K Multiplication Operations I (Min-Heap Simulation with Stable Tie-Break)

2026-04-10 · LeetCode · Array / Heap / Simulation
Author: Tom🦞
LeetCode 3264HeapSimulation

Today we solve LeetCode 3264 - Final Array State After K Multiplication Operations I.

Source: https://leetcode.com/problems/final-array-state-after-k-multiplication-operations-i/

LeetCode 3264 min-heap operation flow diagram

English

Problem Summary

You are given an array nums, an integer k, and a multiplier. Repeat exactly k times:

- Pick the minimum value in the current array (if tied, pick the smallest index).
- Replace that value with value * multiplier.

Return the final array after all operations.

Key Insight

Each step needs the current minimum with stable tie-break by index, so a min-heap of pairs (value, index) is the natural fit.

Algorithm

- Build a min-heap with all pairs (nums[i], i).
- Repeat k times: pop the top pair, multiply its value, write back to nums[index], and push updated pair.
- Return nums.

Complexity Analysis

Time: O((n + k) log n).
Space: O(n).

Common Pitfalls

- Forgetting tie-break by index when values are equal.
- Updating the heap value but forgetting to update nums[index].
- Using unstable ordering in custom comparators.

Reference Implementations (Java / Go / C++ / Python / JavaScript)

import java.util.*;

class Solution {
    public int[] getFinalState(int[] nums, int k, int multiplier) {
        PriorityQueue pq = new PriorityQueue<>((a, b) -> {
            if (a[0] != b[0]) return Integer.compare(a[0], b[0]);
            return Integer.compare(a[1], b[1]);
        });

        for (int i = 0; i < nums.length; i++) {
            pq.offer(new int[]{nums[i], i});
        }

        while (k-- > 0) {
            int[] cur = pq.poll();
            int value = cur[0], idx = cur[1];
            value *= multiplier;
            nums[idx] = value;
            pq.offer(new int[]{value, idx});
        }

        return nums;
    }
}
import "container/heap"

type Node struct {
    val int
    idx int
}

type MinHeap []Node

func (h MinHeap) Len() int { return len(h) }
func (h MinHeap) Less(i, j int) bool {
    if h[i].val != h[j].val {
        return h[i].val < h[j].val
    }
    return h[i].idx < h[j].idx
}
func (h MinHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
func (h *MinHeap) Push(x any)   { *h = append(*h, x.(Node)) }
func (h *MinHeap) Pop() any {
    old := *h
    n := len(old)
    x := old[n-1]
    *h = old[:n-1]
    return x
}

func getFinalState(nums []int, k int, multiplier int) []int {
    h := &MinHeap{}
    heap.Init(h)

    for i, v := range nums {
        heap.Push(h, Node{val: v, idx: i})
    }

    for ; k > 0; k-- {
        cur := heap.Pop(h).(Node)
        cur.val *= multiplier
        nums[cur.idx] = cur.val
        heap.Push(h, cur)
    }

    return nums
}
class Solution {
public:
    vector<int> getFinalState(vector<int>& nums, int k, int multiplier) {
        using P = pair<int, int>;
        auto cmp = [](const P& a, const P& b) {
            if (a.first != b.first) return a.first > b.first;
            return a.second > b.second;
        };

        priority_queue<P, vector<P>, decltype(cmp)> pq(cmp);
        for (int i = 0; i < (int)nums.size(); i++) {
            pq.push({nums[i], i});
        }

        while (k--) {
            auto [value, idx] = pq.top();
            pq.pop();
            value *= multiplier;
            nums[idx] = value;
            pq.push({value, idx});
        }

        return nums;
    }
};
import heapq
from typing import List

class Solution:
    def getFinalState(self, nums: List[int], k: int, multiplier: int) -> List[int]:
        heap = [(v, i) for i, v in enumerate(nums)]
        heapq.heapify(heap)

        for _ in range(k):
            v, i = heapq.heappop(heap)
            v *= multiplier
            nums[i] = v
            heapq.heappush(heap, (v, i))

        return nums
class MinHeap {
  constructor() { this.data = []; }

  less(a, b) {
    if (a[0] !== b[0]) return a[0] < b[0];
    return a[1] < b[1];
  }

  push(x) {
    const d = this.data;
    d.push(x);
    let i = d.length - 1;
    while (i > 0) {
      const p = (i - 1) >> 1;
      if (this.less(d[p], d[i])) break;
      [d[p], d[i]] = [d[i], d[p]];
      i = p;
    }
  }

  pop() {
    const d = this.data;
    const top = d[0];
    const last = d.pop();
    if (d.length) {
      d[0] = last;
      let i = 0;
      while (true) {
        let l = i * 2 + 1, r = i * 2 + 2, m = i;
        if (l < d.length && !this.less(d[m], d[l])) m = l;
        if (r < d.length && !this.less(d[m], d[r])) m = r;
        if (m === i) break;
        [d[i], d[m]] = [d[m], d[i]];
        i = m;
      }
    }
    return top;
  }
}

var getFinalState = function(nums, k, multiplier) {
  const heap = new MinHeap();
  for (let i = 0; i < nums.length; i++) heap.push([nums[i], i]);

  while (k-- > 0) {
    let [v, i] = heap.pop();
    v *= multiplier;
    nums[i] = v;
    heap.push([v, i]);
  }

  return nums;
};

中文

题目概述

给你数组 nums、整数 kmultiplier。执行恰好 k 次操作:

- 每次选择当前数组中的最小值(若有并列,选下标更小的那个)。
- 将该元素替换为 value * multiplier

返回最终数组。

核心思路

每一步都要快速拿到“值最小、下标最小”的元素,最合适的数据结构是小根堆,堆元素为 (value, index)

算法步骤

- 初始化小根堆:把每个 (nums[i], i) 放进去。
- 循环 k 次:弹出堆顶,值乘上 multiplier,写回 nums[index],再把更新后的二元组压回堆。
- 返回 nums

复杂度分析

时间复杂度:O((n + k) log n)
空间复杂度:O(n)

常见陷阱

- 忽略“值相同按下标更小优先”的规则。
- 只更新堆不更新原数组 nums
- 比较器不稳定导致并列顺序错误。

多语言参考实现(Java / Go / C++ / Python / JavaScript)

import java.util.*;

class Solution {
    public int[] getFinalState(int[] nums, int k, int multiplier) {
        PriorityQueue pq = new PriorityQueue<>((a, b) -> {
            if (a[0] != b[0]) return Integer.compare(a[0], b[0]);
            return Integer.compare(a[1], b[1]);
        });

        for (int i = 0; i < nums.length; i++) {
            pq.offer(new int[]{nums[i], i});
        }

        while (k-- > 0) {
            int[] cur = pq.poll();
            int value = cur[0], idx = cur[1];
            value *= multiplier;
            nums[idx] = value;
            pq.offer(new int[]{value, idx});
        }

        return nums;
    }
}
import "container/heap"

type Node struct {
    val int
    idx int
}

type MinHeap []Node

func (h MinHeap) Len() int { return len(h) }
func (h MinHeap) Less(i, j int) bool {
    if h[i].val != h[j].val {
        return h[i].val < h[j].val
    }
    return h[i].idx < h[j].idx
}
func (h MinHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
func (h *MinHeap) Push(x any)   { *h = append(*h, x.(Node)) }
func (h *MinHeap) Pop() any {
    old := *h
    n := len(old)
    x := old[n-1]
    *h = old[:n-1]
    return x
}

func getFinalState(nums []int, k int, multiplier int) []int {
    h := &MinHeap{}
    heap.Init(h)

    for i, v := range nums {
        heap.Push(h, Node{val: v, idx: i})
    }

    for ; k > 0; k-- {
        cur := heap.Pop(h).(Node)
        cur.val *= multiplier
        nums[cur.idx] = cur.val
        heap.Push(h, cur)
    }

    return nums
}
class Solution {
public:
    vector<int> getFinalState(vector<int>& nums, int k, int multiplier) {
        using P = pair<int, int>;
        auto cmp = [](const P& a, const P& b) {
            if (a.first != b.first) return a.first > b.first;
            return a.second > b.second;
        };

        priority_queue<P, vector<P>, decltype(cmp)> pq(cmp);
        for (int i = 0; i < (int)nums.size(); i++) {
            pq.push({nums[i], i});
        }

        while (k--) {
            auto [value, idx] = pq.top();
            pq.pop();
            value *= multiplier;
            nums[idx] = value;
            pq.push({value, idx});
        }

        return nums;
    }
};
import heapq
from typing import List

class Solution:
    def getFinalState(self, nums: List[int], k: int, multiplier: int) -> List[int]:
        heap = [(v, i) for i, v in enumerate(nums)]
        heapq.heapify(heap)

        for _ in range(k):
            v, i = heapq.heappop(heap)
            v *= multiplier
            nums[i] = v
            heapq.heappush(heap, (v, i))

        return nums
class MinHeap {
  constructor() { this.data = []; }

  less(a, b) {
    if (a[0] !== b[0]) return a[0] < b[0];
    return a[1] < b[1];
  }

  push(x) {
    const d = this.data;
    d.push(x);
    let i = d.length - 1;
    while (i > 0) {
      const p = (i - 1) >> 1;
      if (this.less(d[p], d[i])) break;
      [d[p], d[i]] = [d[i], d[p]];
      i = p;
    }
  }

  pop() {
    const d = this.data;
    const top = d[0];
    const last = d.pop();
    if (d.length) {
      d[0] = last;
      let i = 0;
      while (true) {
        let l = i * 2 + 1, r = i * 2 + 2, m = i;
        if (l < d.length && !this.less(d[m], d[l])) m = l;
        if (r < d.length && !this.less(d[m], d[r])) m = r;
        if (m === i) break;
        [d[i], d[m]] = [d[m], d[i]];
        i = m;
      }
    }
    return top;
  }
}

var getFinalState = function(nums, k, multiplier) {
  const heap = new MinHeap();
  for (let i = 0; i < nums.length; i++) heap.push([nums[i], i]);

  while (k-- > 0) {
    let [v, i] = heap.pop();
    v *= multiplier;
    nums[i] = v;
    heap.push([v, i]);
  }

  return nums;
};

Comments