思路
DFS+回溯超时,这里不赘述
对于下标为idx
的元素,nums1[idx]
与nums2[idx]
只有两种情况,交换or不交换。
- 对于
idx==0
而言,可换可不换; - 对于
idx>0
的元素:- 若交换后区间
[0,idx]
内符合严格递增的条件,则应满足nums1[idx] > nums2[idx-1] && nums2[idx] > nums1[idx-1]
- 若不交换,区间
[0,idx]
仍符合严格递增的条件,则应满足nums1[idx] > nums1[idx-1] && nums2[idx] > nums2[idx-1]
- 若交换后区间
动态规划
通过上述分析,我们可以发现,这是一个动态规划的问题。
交换的次数显然是和下标idx
以及前一个元素是否交换有关联的,因此需要一个二维数组来进行求解。令:
dp[i][0]
表示nums1[i]
与nums2[i]
没有交换时,使得两个数组在区间[0,i]
内是严格递增的最小交换次数;dp[i][1]
表示nums1[i]
与nums2[i]
进行交换后,使得两个数组在区间[0,i]
内是严格递增的最小交换次数;
因此转移方程如下,且式中i > 0
:
d p [ i ] [ 0 ] = min { d p [ i − 1 ] [ 0 ] , n u m s 1 [ i ] > n u m s 1 [ i − 1 ] 且 n u m s 2 [ i ] > n u m s 2 [ i − 1 ] d p [ i − 1 ] [ 1 ] , n u m s 1 [ i ] > n u m s 2 [ i − 1 ] 且 n u m s 2 [ i ] > n u m s 1 [ i − 1 ] I N V A L I D , o t h e r w i s e dp[i][0] = \min \left\{ \begin{aligned} dp[i-1][0],& \quad nums1[i] > nums1[i-1] \ 且 \ nums2[i] > nums2[i-1] \\ dp[i-1][1],& \quad nums1[i] > nums2[i-1] \ 且 \ nums2[i] > nums1[i-1] \\ INVALID,& \quad otherwise \end{aligned} \right. dp[i][0]=min⎩ ⎨ ⎧dp[i−1][0],dp[i−1][1],INVALID,nums1[i]>nums1[i−1] 且 nums2[i]>nums2[i−1]nums1[i]>nums2[i−1] 且 nums2[i]>nums1[i−1]otherwise
d p [ i ] [ 1 ] = min { d p [ i − 1 ] [ 0 ] + 1 , n u m s 1 [ i ] > n u m s 2 [ i − 1 ] 且 n u m s 2 [ i ] > n u m s 1 [ i − 1 ] d p [ i − 1 ] [ 1 ] + 1 , n u m s 1 [ i ] > n u m s 1 [ i − 1 ] 且 n u m s 2 [ i ] > n u m s 2 [ i − 1 ] I N V A L I D , o t h e r w i s e dp[i][1] = \min \left\{ \begin{aligned} dp[i-1][0]+1,& \quad nums1[i] > nums2[i-1] \ 且 \ nums2[i] > nums1[i-1] \\ dp[i-1][1]+1,& \quad nums1[i] > nums1[i-1] \ 且 \ nums2[i] > nums2[i-1] \\ INVALID,& \quad otherwise \end{aligned} \right. dp[i][1]=min⎩ ⎨ ⎧dp[i−1][0]+1,dp[i−1][1]+1,INVALID,nums1[i]>nums2[i−1] 且 nums2[i]>nums1[i−1]nums1[i]>nums1[i−1] 且 nums2[i]>nums2[i−1]otherwise
其中
INVALID
值可以设置为n+1
,因为最大交换次数显然不会超过n+1
,使得min
方法能够起作用。
对转移方程进行解释,每次状态转移时我们都需要考虑前面一个元素是否进行过交换。
-
dp[i][0]
表示nums1[i]
与nums2[i]
不进行交换,而不进行交换也可以使得两数组在区间[0,i]
内是严格递增的条件为:nums1[i]>nums1[i-1] && nums2[i] > nums2[i-1]
。但是此时有一个问题,就是nums1[i-1]
和nums2[i-1]
可能已经交换过了,因此需要分两种情况讨论:-
dp[i][0]
由dp[i-1][0]
转移而来,则说明前面没有进行过交换,直接判断nums1[i]>nums1[i-1] && nums2[i] > nums2[i-1]
是否成立即可。 -
dp[i][0]
由dp[i-1][1]
转移而来,则说明前面已经进行过交换了,需要修改判断条件为:nums1[i]>nums2[i-1] && nums2[i] > nums1[i-1]
。
-
-
dp[i][1]
的转移过程同理,只是多加了个1的区别。
对于i=0
的情况,做初始化dp[0][0] = 0, dp[0][1] = 1
。
代码如下:
class Solution {
public int minSwap(int[] nums1, int[] nums2) {
int n = nums1.length;
int[][] dp = new int[n][2];
for (int[] ints : dp) {
Arrays.fill(ints, n);
}
//初始化
dp[0][0] = 0;
dp[0][1] = 1;
for (int i = 1; i < n; i++) {
if (nums1[i] > nums1[i-1] && nums2[i] > nums2[i-1]){
dp[i][0] = Math.min(dp[i][0], dp[i-1][0]);
dp[i][1] = Math.min(dp[i][1], dp[i-1][1]+1);
}
if (nums1[i] > nums2[i-1] && nums2[i] > nums1[i-1]){
dp[i][0] = Math.min(dp[i][0], dp[i-1][1]);
dp[i][1] = Math.min(dp[i][1], dp[i-1][0]+1);
}
}
return Math.min(dp[n-1][0], dp[n-1][1]);
}
}