题目地址:
https://www.lintcode.com/problem/1016
给定两个长度相等的数组 A A A和 B B B,其长度都是 n n n。对于任意 i i i,允许交换 A [ i ] A[i] A[i]和 B [ i ] B[i] B[i],使得两个数组都严格递增。问最少要交换多少次。题目保证解存在。
思路是动态规划。设
f
[
i
]
f[i]
f[i]是不交换
A
[
i
]
A[i]
A[i]和
B
[
i
]
B[i]
B[i]的满足条件的最小交换次数,
g
[
i
]
g[i]
g[i]是交换
A
[
i
]
A[i]
A[i]和
B
[
i
]
B[i]
B[i]的满足条件的最小交换次数。我们分情况讨论:
1、如果
A
[
i
]
>
A
[
i
−
1
]
A[i]>A[i-1]
A[i]>A[i−1]和
B
[
i
]
>
B
[
i
−
1
]
B[i]>B[i-1]
B[i]>B[i−1]有一个不成立,分两种情况,如果不交换
A
[
i
]
A[i]
A[i]和
B
[
i
]
B[i]
B[i]的话,
A
[
i
−
1
]
A[i-1]
A[i−1]和
B
[
i
−
1
]
B[i-1]
B[i−1]必须交换,所以
f
[
i
]
=
g
[
i
−
1
]
f[i]=g[i-1]
f[i]=g[i−1];如果交换
A
[
i
]
A[i]
A[i]和
B
[
i
]
B[i]
B[i]的话,那么
A
[
i
−
1
]
A[i-1]
A[i−1]和
B
[
i
−
1
]
B[i-1]
B[i−1]必须不能交换(交换了就违反严格单调性了),所以
g
[
i
]
=
f
[
i
−
1
]
+
1
g[i]=f[i-1]+1
g[i]=f[i−1]+1;综上
f
[
i
]
=
g
[
i
−
1
]
,
g
[
i
]
=
f
[
i
−
1
]
+
1
f[i]=g[i-1], g[i]=f[i-1]+1
f[i]=g[i−1],g[i]=f[i−1]+12、如果
A
[
i
]
>
A
[
i
−
1
]
A[i]>A[i-1]
A[i]>A[i−1]和
B
[
i
]
>
B
[
i
−
1
]
B[i]>B[i-1]
B[i]>B[i−1]同时成立,分两种情况,如果
A
[
i
]
>
B
[
i
−
1
]
A[i]>B[i-1]
A[i]>B[i−1]和
B
[
i
]
>
A
[
i
−
1
]
B[i]>A[i-1]
B[i]>A[i−1]同时成立,对于
f
[
i
]
f[i]
f[i],
A
[
i
−
1
]
A[i-1]
A[i−1]和
B
[
i
−
1
]
B[i-1]
B[i−1]可以换,也可以不换,所以
f
[
i
]
=
min
{
f
[
i
−
1
]
,
g
[
i
−
1
]
}
f[i]=\min\{f[i-1],g[i-1]\}
f[i]=min{f[i−1],g[i−1]},对于
g
[
i
]
g[i]
g[i]也是类似,所以
g
[
i
]
=
min
{
f
[
i
−
1
]
,
g
[
i
−
1
]
}
+
1
g[i]=\min\{f[i-1],g[i-1]\}+1
g[i]=min{f[i−1],g[i−1]}+1,即
f
[
i
]
=
min
{
f
[
i
−
1
]
,
g
[
i
−
1
]
}
,
g
[
i
]
=
min
{
f
[
i
−
1
]
,
g
[
i
−
1
]
}
+
1
f[i]=\min\{f[i-1],g[i-1]\},g[i]=\min\{f[i-1],g[i-1]\}+1
f[i]=min{f[i−1],g[i−1]},g[i]=min{f[i−1],g[i−1]}+1如果
A
[
i
]
>
B
[
i
−
1
]
A[i]>B[i-1]
A[i]>B[i−1]和
B
[
i
]
>
A
[
i
−
1
]
B[i]>A[i-1]
B[i]>A[i−1]有一个不成立,考虑
f
[
i
]
f[i]
f[i],那么
A
[
i
−
1
]
A[i-1]
A[i−1]和
B
[
i
−
1
]
B[i-1]
B[i−1]一定不能换,所以
f
[
i
]
=
f
[
i
−
1
]
f[i]=f[i-1]
f[i]=f[i−1],同理考虑
g
[
i
]
g[i]
g[i],那么
A
[
i
−
1
]
A[i-1]
A[i−1]和
B
[
i
−
1
]
B[i-1]
B[i−1]一定要换,所以
g
[
i
]
=
g
[
i
−
1
]
+
1
g[i]=g[i-1]+1
g[i]=g[i−1]+1。即
f
[
i
]
=
f
[
i
−
1
]
,
g
[
i
]
=
g
[
i
−
1
]
+
1
f[i]=f[i-1],g[i]=g[i-1]+1
f[i]=f[i−1],g[i]=g[i−1]+1代码如下:
public class Solution {
/**
* @param A: an array
* @param B: an array
* @return: the minimum number of swaps to make both sequences strictly increasing
*/
public int minSwap(int[] A, int[] B) {
// Write your code here
int n = A.length;
if (n == 0) {
return 0;
}
int[][] dp = new int[n][2];
dp[0][0] = 0;
dp[0][1] = 1;
for (int i = 1; i < n; i++) {
if (A[i] > A[i - 1] && B[i] > B[i - 1]) {
if (A[i] > B[i - 1] && B[i] > A[i - 1]) {
dp[i][0] = Math.min(dp[i - 1][0], dp[i - 1][1]);
dp[i][1] = Math.min(dp[i - 1][0], dp[i - 1][1]) + 1;
} else {
dp[i][0] = dp[i - 1][0];
dp[i][1] = dp[i - 1][1] + 1;
}
} else {
dp[i][0] = dp[i - 1][1];
dp[i][1] = dp[i - 1][0] + 1;
}
}
return Math.min(dp[n - 1][0], dp[n - 1][1]);
}
}
时空复杂度 O ( n ) O(n) O(n)。