Given an array nums of even length n and an integer limit, you are to make the array complementary.
An array is complementary if for every pair (nums[i], nums[n - 1 - i]) (for all i from 0 to n/2 - 1), the sum is equal to the same value for every pair.
For each pair, you are allowed to change either or both numbers to any integer in the range [1, limit]. Changing a number counts as one move. Return the minimum total moves needed to make the array complementary.
2 <= n <= 10^5, 1 <= limit <= 10^5, 1 <= nums[i] <= limit, n is even.
At first glance, a brute-force approach would check every possible target sum for all pairs, and for each, count the moves needed. But with large n and limit, this is not feasible.
We need to figure out, for each possible sum S (from 2 to 2 * limit), how many moves it would take to make every pair's sum equal to S. For a pair (a, b), we notice:
a + b == S, no moves are needed.S (and it's within [1, limit]), that's one move.S without iterating over all pairs for each S.
This leads us to an interval/difference array approach, where we can efficiently count the number of pairs requiring 0, 1, or 2 moves for each possible sum.
(nums[i], nums[n-1-i]) for i from 0 to n/2-1.(a, b):
a + b needs 0 moves if we target that sum.[min(a, b)+1, max(a, b)+limit] using one move.diff of size 2 * limit + 2 to efficiently track, for each possible sum S, the number of additional moves needed.diff[2] by 2 (every sum starts with 2 moves by default).diff[min(a, b)+1] by 1 (from this point, only 1 move is needed).diff[a+b] by 1 (from this point, 0 moves are needed).diff[a+b+1] by 1 (exit 0 move interval, back to 1 move).diff[max(a, b)+limit+1] by 1 (exit 1 move interval, back to 2 moves).diff to get the number of moves needed for each possible sum S.This approach is efficient because it processes all pairs in O(n) time and computes the result for all possible sums in O(limit) time.
Suppose nums = [1,2,4,3], limit = 4. The pairs are (1,3) and (2,4).
a=1, b=3
a=2, b=4
We use the difference array as described. After processing both pairs and computing prefix sums, we find for each possible sum (from 2 to 8) the number of moves required. The minimum is 1, which is the answer.
We efficiently solve the "Minimum Moves to Make Array Complementary" problem by leveraging a difference array to track the number of moves needed for each possible target sum. By analyzing the range of sums achievable with 0, 1, or 2 moves for each pair, and aggregating this information, we avoid brute-force enumeration and achieve an O(n + limit) solution. This approach highlights the power of interval counting and prefix sums in optimizing problems involving ranges and cumulative effects.
class Solution:
def minMoves(self, nums: List[int], limit: int) -> int:
n = len(nums)
diff = [0] * (2 * limit + 2)
for i in range(n // 2):
a, b = nums[i], nums[n - 1 - i]
low = 1 + min(a, b)
high = limit + max(a, b)
s = a + b
diff[2] += 2
diff[low] -= 1
diff[s] -= 1
diff[s + 1] += 1
diff[high + 1] += 1
res = float('inf')
curr = 0
for S in range(2, 2 * limit + 1):
curr += diff[S]
res = min(res, curr)
return res
class Solution {
public:
int minMoves(vector<int>& nums, int limit) {
int n = nums.size();
vector<int> diff(2 * limit + 2, 0);
for (int i = 0; i < n / 2; ++i) {
int a = nums[i], b = nums[n - 1 - i];
int low = 1 + min(a, b);
int high = limit + max(a, b);
int s = a + b;
diff[2] += 2;
diff[low] -= 1;
diff[s] -= 1;
diff[s + 1] += 1;
diff[high + 1] += 1;
}
int res = INT_MAX, curr = 0;
for (int S = 2; S <= 2 * limit; ++S) {
curr += diff[S];
res = min(res, curr);
}
return res;
}
};
class Solution {
public int minMoves(int[] nums, int limit) {
int n = nums.length;
int[] diff = new int[2 * limit + 2];
for (int i = 0; i < n / 2; ++i) {
int a = nums[i], b = nums[n - 1 - i];
int low = 1 + Math.min(a, b);
int high = limit + Math.max(a, b);
int s = a + b;
diff[2] += 2;
diff[low] -= 1;
diff[s] -= 1;
diff[s + 1] += 1;
diff[high + 1] += 1;
}
int res = Integer.MAX_VALUE, curr = 0;
for (int S = 2; S <= 2 * limit; ++S) {
curr += diff[S];
res = Math.min(res, curr);
}
return res;
}
}
var minMoves = function(nums, limit) {
const n = nums.length;
const diff = new Array(2 * limit + 2).fill(0);
for (let i = 0; i < n / 2; ++i) {
const a = nums[i], b = nums[n - 1 - i];
const low = 1 + Math.min(a, b);
const high = limit + Math.max(a, b);
const s = a + b;
diff[2] += 2;
diff[low] -= 1;
diff[s] -= 1;
diff[s + 1] += 1;
diff[high + 1] += 1;
}
let res = Number.MAX_SAFE_INTEGER, curr = 0;
for (let S = 2; S <= 2 * limit; ++S) {
curr += diff[S];
res = Math.min(res, curr);
}
return res;
};