1674. Minimum Moves to Make Array Complementary - cocoder39/coco39_LC GitHub Wiki
1674. Minimum Moves to Make Array Complementary
explanation: check post + comments in this page
1 <= nums[i] <= limit
Thinking process:
- 3 initial situations:
- T < A + B
- diff = A+B-T and the max reduction we can achieve within 1 operation is max(A,B) - 1
- max(A,B) - 1 >= diff => max(A,B) - 1 >= A+B-T => T >= A+B-max(A,B) + 1 = min(A,B) + 1
- so min(A,B) + 1 <= T < A+B => 1 operation
- max(A,B) - 1 < diff => 2 <= T < min(A,B) + 1 => 2 operations
- T = A + B => 0 operation
- T > A + B
- max increase we can achieve within 1 operation is limit - min(A,B)
- limit - min(A,B) >= diff => limit - min(A,B) >= T - A - B => T <= max(A, B) + limit
- so A+B < T <= max(A, B) + limit => 1 operation
- limit + min(A,B) < diff => max(A, B) + limit < T <= 2*limit => 2 operations
Summary
- 2 <= T < min(A, B) + 1 => 2 operations and left boundary is 2
- min(A, B) + 1 <= T < A + B => 1 operation and left boundary is min(A, B) + 1
- T = A + B => 0 operation and left boundary is A+B
- A+B < T <= max(A,B) + limit => 1 operation and left boundary is A+B + 1
- max(A,B) + limit + 1 <= target < 2*limit => 2 operations and left boundary is max(A,B) + limit
class Solution:
def minMoves(self, nums: List[int], limit: int) -> int:
delta = collections.Counter()
n = len(nums)
for i in range(n // 2):
a, b = nums[i], nums[n - 1 - i]
delta[2] += 2
delta[min(a, b) + 1] -= 1
delta[a + b] -= 1
delta[a + b + 1] += 1
delta[max(a, b) + limit + 1] += 1
res = float("inf")
cur = 0
for i in range(2, 2*limit + 1):
cur += delta[i]
res = min(res, cur)
return res
2 key points:
- boundary analysis
- difference array:
- efficient: delta[i] represents incremental diff between delta[i-1] and delta[i]. This way we don't need to update delta falling into a range (eg, 2 <= T < min(A, B) + 1) because the diff between delta[i-1] and delta[i] is always 0 in the range
- avoid duplicated boundary eg, 2 can be equal to min(A, B) + 1