greedy
accumulate
]
Leetcode 1674 Minimum Moves to Make Array Complementary
Problem statement
https://leetcode.com/problems/minimum-moves-to-make-array-complementary/
Solution
The idea for each pair of complementary numbers, imagine 3, 4 and limit = 6. Then we can get numbers from 2 to 12, and we need the following number of moves:
[inf, inf, 2, 2, 1, 1, 1, 0, 1, 1, 1, 2, 2]
So, to get 7 we need zero moves, because 3 + 4 already equal to 7. To get 4, 5, 6 we can make 1 move: for example to get 4 we can make it as 3 + 1, and so on. Also we can get numbers 8, 9, 10, using 1 move. In general, to make 1 move, we can get numbers from min(a,b) + 1 to max(a,b) + limit.
Now, we need to get this array for all pairs of complementary numbers and sum all of them and find element with smallest value. There is a trick, how we can do it efficiently: first of all, let us invert array, that is consider
[inf, inf, 0, 0, 1, 1, 1, 2, 1, 1, 1, 0, 0].
And then we use cumulative sums trick, if we add two following arrays, than cumulative sum will be exactly what we need.
[inf, inf, 0, 0, 1, 0, 0, 0, 0, 0, 0, -1, 0]
[inf, inf, 0, 0, 0, 0, 0, 1, -1, 0, 0, 0, 0]
So, we just do what we discussed, and get the solution.
Complexity
Time complexity O(n + k), where k is our limit and n is length of nums. Space complexity is O(k).
Code
class Solution:
def minMoves(self, nums, k):
n = len(nums)//2
diffs = [0]*(2*k+2)
for i in range(n):
a, b = nums[i], nums[-1-i]
diffs[min(a,b) + 1] += 1
diffs[max(a,b) + k+1] -= 1
diffs[a+b] += 1
diffs[a+b+1] -= 1
return 2*n - max(accumulate(diffs))
Remark
See similar Problem 0798 Smallest Rotation with Highest Score.