Given two integer arrays A
and B
of the same length, your task is to make both sequences strictly increasing by swapping elements at the same index (i.e., swap A[i]
with B[i]
for any i
). You can choose to swap or not at each index, but you must ensure that after all swaps, both arrays are strictly increasing:
A[0] < A[1] < ... < A[n-1]
B[0] < B[1] < ... < B[n-1]
Return the minimum number of swaps required to achieve this. It is guaranteed that there is always at least one valid solution.
Constraints:
A.length
= B.length
≤ 1000A[i]
, B[i]
<= 2000At first glance, the problem suggests checking all possible combinations of swaps, but with arrays up to length 1000, brute-force is not feasible due to the exponential number of possibilities.
Instead, we observe that at each index, we have two choices: swap or not swap. Our decision at each step affects future decisions because the sequences must remain strictly increasing. Thus, we need to keep track of two states at each index:
By keeping track of these two states, we can use dynamic programming to efficiently find the minimum number of swaps required.
We use dynamic programming to solve the problem efficiently. Here’s the step-by-step breakdown:
keep[i]
: The minimum swaps needed to make sequences increasing up to index i
without swapping at i
.swap[i]
: The minimum swaps needed up to index i
with a swap at i
.keep[0] = 0
).swap[0] = 1
).i
from 1 to n-1
, check two conditions:
A[i] > A[i-1]
and B[i] > B[i-1]
: No swap needed at i
if previous was not swapped, or swap at i
if previous was swapped.
A[i] > B[i-1]
and B[i] > A[i-1]
: Current swap status can be the opposite of previous (swap or not swap).
keep[i]
and swap[i]
accordingly, taking the minimum swaps for each possibility.
min(keep[n-1], swap[n-1])
, the minimal swaps required at the last index.This approach only needs to store the previous state, so we can optimize space to O(1) by using two variables instead of arrays.
Example:
A = [1, 3, 5, 4]
B = [1, 2, 3, 7]
keep[0] = 0
swap[0] = 1
A[1]=3 > A[0]=1
and B[1]=2 > B[0]=1
so both sequences are increasing without swap.keep[1] = keep[0] = 0
(no swap at 1)swap[1] = swap[0] + 1 = 2
(swap at both 0 and 1)
A[1]=3 > B[0]=1
and B[1]=2 > A[0]=1
so swapping only at 1 is possible:
swap[1] = min(swap[1], keep[0] + 1) = min(2, 1) = 1
keep[1] = min(keep[1], swap[0]) = min(0, 1) = 0
A[2]=5 > A[1]=3
and B[2]=3 > B[1]=2
so
keep[2] = keep[1] = 0
swap[2] = swap[1] + 1 = 2
A[2]=5 > B[1]=2
and B[2]=3 > A[1]=3
(false, 3 is not greater than 3), so no update here.
A[3]=4 > A[2]=5
is false, so no update for keep.A[3]=4 > B[2]=3
and B[3]=7 > A[2]=5
is true, so we can swap at 3 if we didn't swap at 2.swap[3] = min(swap[3], keep[2] + 1) = min(inf, 1) = 1
keep[3] = min(keep[3], swap[2]) = min(inf, 2) = 2
min(keep[3], swap[3]) = min(2, 1) = 1
Thus, only 1 swap is needed (at index 3).
The key insight is that at each index, the decision to swap or not depends only on the previous state. By using dynamic programming to track the minimum swaps needed for both cases (swap, no swap), we efficiently compute the answer in linear time. This approach elegantly avoids brute-force enumeration and leverages the problem's sequential structure for optimal performance.
class Solution:
def minSwap(self, A, B):
n = len(A)
keep = 0
swap = 1
for i in range(1, n):
keep2 = swap2 = float('inf')
if A[i] > A[i-1] and B[i] > B[i-1]:
keep2 = min(keep2, keep)
swap2 = min(swap2, swap + 1)
if A[i] > B[i-1] and B[i] > A[i-1]:
keep2 = min(keep2, swap)
swap2 = min(swap2, keep + 1)
keep, swap = keep2, swap2
return min(keep, swap)
class Solution {
public:
int minSwap(vector<int>& A, vector<int>& B) {
int n = A.size();
int keep = 0, swap = 1;
for (int i = 1; i < n; ++i) {
int keep2 = INT_MAX, swap2 = INT_MAX;
if (A[i] > A[i-1] && B[i] > B[i-1]) {
keep2 = min(keep2, keep);
swap2 = min(swap2, swap + 1);
}
if (A[i] > B[i-1] && B[i] > A[i-1]) {
keep2 = min(keep2, swap);
swap2 = min(swap2, keep + 1);
}
keep = keep2;
swap = swap2;
}
return min(keep, swap);
}
};
class Solution {
public int minSwap(int[] A, int[] B) {
int n = A.length;
int keep = 0, swap = 1;
for (int i = 1; i < n; i++) {
int keep2 = Integer.MAX_VALUE, swap2 = Integer.MAX_VALUE;
if (A[i] > A[i-1] && B[i] > B[i-1]) {
keep2 = Math.min(keep2, keep);
swap2 = Math.min(swap2, swap + 1);
}
if (A[i] > B[i-1] && B[i] > A[i-1]) {
keep2 = Math.min(keep2, swap);
swap2 = Math.min(swap2, keep + 1);
}
keep = keep2;
swap = swap2;
}
return Math.min(keep, swap);
}
}
var minSwap = function(A, B) {
let n = A.length;
let keep = 0, swap = 1;
for (let i = 1; i < n; i++) {
let keep2 = Infinity, swap2 = Infinity;
if (A[i] > A[i-1] && B[i] > B[i-1]) {
keep2 = Math.min(keep2, keep);
swap2 = Math.min(swap2, swap + 1);
}
if (A[i] > B[i-1] && B[i] > A[i-1]) {
keep2 = Math.min(keep2, swap);
swap2 = Math.min(swap2, keep + 1);
}
keep = keep2;
swap = swap2;
}
return Math.min(keep, swap);
};