We have two integer sequences A
and B
of the same non-zero length.
We are allowed to swap elements A[i]
and B[i]
. Note that both elements are in the same index position in their respective sequences.
At the end of some number of swaps, A
and B
are both strictly increasing. (A sequence is strictly increasing if and only if A[0] < A[1] < A[2] < ... < A[A.length - 1]
.)
Given A and B, return the minimum number of swaps to make both sequences strictly increasing. It is guaranteed that the given input always makes it possible.
Example:
Input: A = [1,3,5,4], B = [1,2,3,7]
Output: 1
Explanation:
Swap A[3] and B[3]. Then the sequences are:
A = [1, 3, 5, 7] and B = [1, 2, 3, 4]
which are both strictly increasing.
Note:
A, B
are arrays with the same length, and that length will be in the range[1, 1000]
.A[i], B[i]
are integer values in the range[0, 2000]
.
Solution
一次DP不能解决问题,如果DP是一个一维数组,DP[i]
表示,在第i个位置上需要交换的最小次数,那么如何从DP[i-1]
中推得DP[i]
的值呢?
事实上,很难,考虑如下场景
0 4 4 5
0 1 6 8
这里我们可以交换1和4,也可以交换4和6,到底交换谁就不好说,如果交换1和4,那么交换次数为1,如果交换4和6,那么后续还要交换5和8,但是DP
是从小问题推到大问题,我们无法从求DP[i-1]
时就预知后面发生的事情
所以需要看两位,也就是i-1
和i
,需要定义两个DP
数组,分别表示当前需要交换和不需要交换两种状态
如果A[i-1] < A[i] && B[i-1] < B[i]
的话,那么已经有序了
可以交换,也可以不交换:
i
交换的话,则两个位置上的元素都要交换,才能保证交换后的序列依然有序,swap[i] = swap[i-1] + 1
ii
不交换的话,则noswap[i] = swap[i]
如果A[i-1] < B[i] && B[i-1] < A[i]
的话,那么必须要交换,又有两种情况
i
交换i位置,i-1
位置不交换,则swap[i] = noswap[i-1] + 1
ii
交换i-1
位置,i
位置不交换,则noswap[i] = swap[i-1]
#define min(a, b) (a) < (b) ? (a) : (b)
int minSwap(int* A, int ASize, int* B, int BSize) {
const int n = ASize;
int i;
int swap[n], noswap[n];
for (i = 0; i < n; i++) swap[i] = INT_MAX;
for (i = 0; i < n; i++) noswap[i] = INT_MAX;
swap[0] = 1;
noswap[0] = 0;
for (i = 1; i < n; i++) {
if (A[i - 1] < A[i] && B[i - 1] < B[i]) {
// Swapped A[i - 1] / B[i - 1], swap A[i] / B[i] as well
swap[i] = swap[i - 1] + 1;
// Good case, no need swap for A[i] and B[i]
noswap[i] = noswap[i - 1];
}
if (A[i - 1] < B[i] && B[i - 1] < A[i]) {
// A[i - 1] / B[i - 1] not swapped
swap[i] = min(swap[i], noswap[i - 1] + 1);
// Swap A[i - 1] / B[i - 1], not swap A[i] / B[i]
noswap[i] = min(noswap[i], swap[i - 1]);
// 用min的目的是假如在第一个if中也满足条件的话,取两者交换次数最小的
}
}
return min(swap[n - 1], noswap[n - 1]);
}