LeetCode 3937 - Minimum Operations to Make Array Modulo Alternating I
The problem asks us to transform an array of integers, nums, into a modulo alternating array with the minimum number of operations, where each operation is either incrementing or decrementing an element by 1.
Difficulty: 🟡 Medium
Topics: —
Solution
Problem Understanding
The problem asks us to transform an array of integers, nums, into a modulo alternating array with the minimum number of operations, where each operation is either incrementing or decrementing an element by 1. A modulo alternating array is defined with respect to an integer k and two distinct residues x and y in the range [0, k-1]: all elements at even indices must satisfy nums[i] % k == x and all elements at odd indices must satisfy nums[i] % k == y. The goal is to compute the fewest operations needed to achieve this.
The inputs are:
nums, an array of integers, length between 1 and 100, each element up to 10^9.k, an integer between 2 and 100.
The output is a single integer representing the minimum operations. Because nums can contain very large numbers, we need an approach that efficiently computes how far each number is from satisfying the modulo condition without brute-forcing all possibilities.
Important edge cases include:
- Small arrays (length 1 or 2) where one operation may suffice.
- Arrays where all elements are identical.
- Situations where multiple modulo residues are equally costly to achieve.
- Large numbers that require careful subtraction/addition to reach the target modulo.
Approaches
Brute-force approach: Consider all pairs of distinct residues (x, y) in [0, k-1]. For each pair, calculate the number of operations required to transform each element at even indices to x modulo k and each element at odd indices to y modulo k. Choose the pair that minimizes the sum of operations. While this works correctly, it requires iterating over O(k^2) pairs and for each, potentially O(n) computations. For maximum k=100 and n=100, this gives O(n*k^2) operations, which is feasible but can be optimized further.
Optimal approach: The key insight is that for each index parity (even or odd), we can precompute the cost to convert all numbers to each possible modulo value. This reduces the repeated computation for each (x, y) pair. Specifically:
- Maintain two arrays
even_costsandodd_costsof lengthk, whereeven_costs[r]stores the total operations needed to convert all even-index elements to modulor, and similarly forodd_costs[r]. - Then iterate over all distinct residue pairs
(x, y)to computeeven_costs[x] + odd_costs[y]and find the minimum.
This avoids recalculating per-element costs for each residue pair, improving efficiency while keeping the approach straightforward.
| Approach | Time Complexity | Space Complexity | Notes |
|---|---|---|---|
| Brute Force | O(n * k^2) | O(1) | Iterates over all residue pairs and all elements |
| Optimal | O(n * k + k^2) | O(k) | Precomputes per-residue costs for even/odd indices, then iterates over pairs |
Algorithm Walkthrough
- Initialize two arrays
even_costsandodd_costsof sizekfilled with zeros. Each will store the total number of operations to convert even or odd indexed numbers to a particular modulo residue. - Iterate through
numsby indexi. For each elementnums[i]and each residuerin[0, k-1], compute the minimum operations to convertnums[i]to havenums[i] % k == r. This can be computed as the minimal distance in modulokarithmetic:min((nums[i] - r) % k, (r - nums[i]) % k). Add this cost to eithereven_costs[r]orodd_costs[r]depending on whetheriis even or odd. - After precomputing the costs, iterate over all pairs of residues
(x, y)wherex != y. For each pair, computetotal_cost = even_costs[x] + odd_costs[y]and maintain the minimum total cost. - Return the minimum total cost.
Why it works: By precomputing the conversion cost for each modulo residue per index parity, we ensure that the cost of converting all elements to any (x, y) pair is computed efficiently and correctly. The algorithm checks all valid residue pairs, guaranteeing that the minimum is found.
Python Solution
class Solution:
def minOperations(self, nums: list[int], k: int) -> int:
n = len(nums)
even_costs = [0] * k
odd_costs = [0] * k
for i, num in enumerate(nums):
for r in range(k):
# Minimum number of operations to make num % k == r
cost = min((num - r) % k, (r - num) % k)
if i % 2 == 0:
even_costs[r] += cost
else:
odd_costs[r] += cost
min_ops = float('inf')
for x in range(k):
for y in range(k):
if x != y:
min_ops = min(min_ops, even_costs[x] + odd_costs[y])
return min_ops
The Python code first precomputes the conversion costs for all possible modulo residues separately for even and odd indices. Then it iterates over all distinct residue pairs to find the minimal total cost. Using min((num - r) % k, (r - num) % k) ensures the correct number of operations regardless of whether the element is larger or smaller than the target modulo.
Go Solution
func minOperations(nums []int, k int) int {
n := len(nums)
evenCosts := make([]int, k)
oddCosts := make([]int, k)
for i, num := range nums {
for r := 0; r < k; r++ {
cost := min((num - r + k) % k, (r - num + k) % k)
if i % 2 == 0 {
evenCosts[r] += cost
} else {
oddCosts[r] += cost
}
}
}
minOps := 1 << 60
for x := 0; x < k; x++ {
for y := 0; y < k; y++ {
if x != y {
if evenCosts[x]+oddCosts[y] < minOps {
minOps = evenCosts[x] + oddCosts[y]
}
}
}
}
return minOps
}
func min(a, b int) int {
if a < b {
return a
}
return b
}
The Go solution mirrors the Python implementation. We carefully handle modulo arithmetic by adding k before taking % k to avoid negative numbers, and we use a large initial value for minOps instead of inf. Otherwise, the logic is identical.
Worked Examples
Example 1: nums = [1,4,2,8], k = 3
- Precompute costs for even indices (
i = 0, 2):
For x=0: cost = 1+2=3, x=1: cost=0+1=1, x=2: cost=2+0=2
even_costs = [3,1,2]
2. Precompute costs for odd indices (i = 1, 3):
For y=0: cost=1+1=2, y=1: cost=2+2=4, y=2: cost=0+1=1
odd_costs = [2,4,1]
3. Iterate over distinct pairs (x,y) and compute total_cost:
(1,2) => 1+1=2 (minimum)
Example 2: nums = [1,1,1], k = 3
- even_costs for
i=0,2:[1,1,0] - odd_costs for
i=1:[1,0,2] - Best pair
(0,1)gives total_cost = 1, which matches the expected output.
Complexity Analysis
| Measure | Complexity | Explanation |
|---|---|---|
| Time | O(n * k + k^2) | Precomputing costs takes O(n*k), checking all pairs of residues takes O(k^2) |
| Space | O(k) | Two arrays of size k for even and odd costs |
The algorithm is efficient given the constraints (n <= 100, k <= 100) and avoids recalculating per-element costs unnecessarily.
Test Cases
# Provided examples
assert Solution().minOperations([1,4,2,8], 3) == 2 # Example 1
assert Solution().minOperations([1,1,1], 3) == 1 # Example 2
# Edge cases
assert Solution().minOperations([1], 2) == 0 # Single element, already alternating
assert Solution().minOperations([1,2], 2) == 0 # Two elements already satisfying different modulo
assert Solution().minOperations([2,2,2,2], 3) ==