题目
我们有两个长度相等且不为空的整型数组 A 和 B 。
我们可以交换 A[i] 和 B[i] 的元素。注意这两个元素在各自的序列中应该处于相同的位置。
在交换过一些元素之后,数组 A 和 B 都应该是严格递增的(数组严格递增的条件仅为A[0] < A[1] < A[2] < … < A[A.length - 1])。
给定数组 A 和 B ,请返回使得两个数组均保持严格递增状态的最小交换次数。假设给定的输入总是有效的。
实例
示例:
输入: A = [1,3,5,4], B = [1,2,3,7]
输出: 1
解释:
交换 A[3] 和 B[3] 后,两个数组如下:
A = [1, 3, 5, 7] , B = [1, 2, 3, 4]
两个数组均为严格递增的。
解题思路
- 本题属于动态规划求最大最小值的一类问题,那么首先就要先确定问题的状态,从而求的子问题,最后写出动态转移方程进行求解。
确定状态
- 首先看问题『返回使得两个数组均保持严格递增状态的最小交换次数』,因此可以定义change[i]为在A[i]和B[i]交换的情况下,前i个数达到递增状态需要交换多少次,un_change[i]为在A[i]和B[i]不交换的情况下,前i个数达到递增状态需要交换多少次,而chane和un_change的存在就涉及到了选与不选的问题。
下面开始分情况讨论:
- 当 A[i] > A[i-1] && B[i] > B[i-1] 时,说明前i个数已经达到了递增状态,在此基础上可以在分为两类:
- 1.当 A[i] > B[i-1] && B[i] > A[i-1] 时,说明A[i]和B[i]是可以交换的,那么就可以得出一下两个状态方程:
- A[i]与B[i]交换 : change[i] = min(un_change[i-1] , change[i-1]) + 1
- A[i]与B[i]不交换:un_change[i] = min(un_change[i-1] , change[i])
- 当1条件不成立时,那么A[i]与B[i]交换,A[i-1]与B[i-1]也必须交换,也就是i和i-1同时行动。
- 交换:change[i] = change[i-1] + 1
- 不交换:un_change[i] = un_change[i]
- 1.当 A[i] > B[i-1] && B[i] > A[i-1] 时,说明A[i]和B[i]是可以交换的,那么就可以得出一下两个状态方程:
- 当 A[i] > A[i-1] && B[i] > B[i-1] 不成立时,如果交换A[i]和B[i],则i-1不用交换,如果不交换A[i]和B[i],则交换i-1。(刚开始搞不明白为什么这里会成立,后来发现题目要求了给定的输入一定是有效的,因此只要保证前面是递增状态,后面交换一定会保证递增状态)
- 交换:change[i] = unchange[i-1] + 1
- 不交换: unchange[i] = change[i-1]
- 最后取出 min(change[A.len-1] , un_change[A.len-1]) 即可
代码
class Solution {
public int minSwap(int[] A, int[] B) {
int len = A.length;
int change[] = new int[len];
int un_change[] = new int[len];
change[0] = 1;
un_change[0] = 0;
for(int i = 1; i < len; i++){
if(A[i] > A[i-1] && B[i] > B[i-1]){
if(A[i] > B[i-1] && B[i] > A[i-1]){
change[i] = Math.min(change[i-1],un_change[i-1]) + 1;
un_change[i] = Math.min(change[i-1],un_change[i-1]);
}else{
change[i] = change[i-1] + 1;
un_change[i] = un_change[i-1];
}
}else{
change[i] = un_change[i-1] + 1;
un_change[i] = change[i-1];
}
}
return Math.min(change[len-1],un_change[len-1]);
}
}