题目描述
我们有两个长度相等且不为空的整型数组 nums1 和 nums2 。在一次操作中,我们可以交换 nums1[i] 和 nums2[i]的元素。
例如,如果 nums1 = [1,2,3,8] , nums2 =[5,6,7,4] ,你可以交换 i = 3 处的元素,得到 nums1 =[1,2,3,4] 和 nums2 =[5,6,7,8] 。
返回 使 nums1 和 nums2 严格递增 所需操作的最小次数 。
数组 arr 严格递增 且 arr[0] < arr[1] < arr[2] < ... < arr[arr.length - 1] 。
注意:
用例保证可以实现操作。
示例 1:
输入: nums1 = [1,3,5,4], nums2 = [1,2,3,7]
输出: 1
解释:
交换 A[3] 和 B[3] 后,两个数组如下:
A = [1, 3, 5, 7] , B = [1, 2, 3, 4]
两个数组均为严格递增的。
解题思路
这道题我是查看其他人的解题思路后,解答出来的,下面给出我理解后的思路:
给定的两个数组,并且可以相同位置做交换,并且要保持严格递增。按照这个要求:枚举以下情况做分析:
case 1:
满足:num1[i]>num1[i-1] && num2[i]>num2[i-1] 并且 num1[i]>num2[i-1] && num2[i]>num1[i-1]
num1=[1,3]
num2=[2,4]
上述数组满足case1, 这个时候 nums1[0] 和 nums2[0] 可以做交换,nums1[1] 和 nums2[1]也可以做交换,但是实际最小值是0;
如果有dp[i][0]表示不需要交换最小的次数,dp[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
case 2:
num1[i]>num1[i-1] && num2[i]>num2[i-1]
num1=[1,2]
num2=[3,4]
上述数组满足case2, 这个时候 nums1[0] 和 nums2[0] 如果要做交换,那么nums1[1] 和 nums2[1]也一定要交换,那么要么是0,要么是2;
如果有dp[i][0]表示不需要交换最小的次数,dp[i][1]表示需要交换最小的次数,那么有:
dp[i][0]=dp[i-1][0]
dp[i][1]=dp[i-1][1] + 1
case 3:
num1=[1,4]
num2=[3,2]
上述数组满足case3, 这个时候 nums1[1] 和 nums2[1] 只有做交换后才能满足条件;
如果有dp[i][0]表示不需要交换最小的次数,dp[i][1]表示需要交换最小的次数,那么有:
dp[i][0]=dp[i-1][1]
dp[i][1]=dp[i-1][0] + 1
代码实现
class Solution1 {
public int minSwap(int[] nums1, int[] nums2) {
int dp[][] = new int[nums1.length][2];
dp[0][0] = 0;
dp[0][1] = 1;
for (int i = 1; i < nums1.length; i++) {
if ((nums1[i - 1] < nums1[i] && nums2[i - 1] < nums2[i])
&& (nums1[i - 1] < nums2[i] && nums2[i - 1] < nums1[i])) {
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 if (nums1[i - 1] < nums1[i] && nums2[i - 1] < nums2[i]) {
dp[i][0] = dp[i - 1][0];
dp[i][1] = dp[i - 1][1] + 1;
} else if (nums1[i - 1] < nums2[i] && nums2[i - 1] < nums1[i]) {
dp[i][0] = dp[i - 1][1];
dp[i][1] = dp[i - 1][0] + 1;
} else {
throw new RuntimeException("not supported");
}
}
return Math.min(dp[nums1.length - 1][0], dp[nums1.length - 1][1]);
}
public static void main(String[] args) {
Solution1 solution = new Solution1();
// System.out.println(solution.minSwap(new int[]{1, 3, 5, 4}, new int[]{1, 2, 3, 7}));
// System.out.println(solution.minSwap(new int[]{3,3,8,9,10}, new int[]{1,7,4,6,8}));
int num1[] = new int[]{1, 8, 4, 6, 7, 8, 16, 18, 19, 29, 25, 26, 35, 31, 38, 35, 37, 41, 39, 43, 48, 49, 46, 47, 50, 52, 54, 55, 63, 58, 67, 63, 69, 71, 74, 73, 76, 77, 80, 78, 79, 80, 86, 87, 90, 93, 95, 96, 97, 100, 101, 105, 106, 108, 108, 109, 116, 111, 119, 121, 122, 124, 130, 125, 126, 127, 128, 140, 144, 135, 148, 151, 143, 154, 155, 157, 160, 156, 158, 159, 168, 170, 163, 173, 175, 176, 177, 180, 177, 182, 183, 184, 185, 190, 191, 194, 194, 195, 196, 200};
int num2[] = new int[]{7, 3, 12, 14, 19, 22, 24, 26, 27, 21, 30, 31, 28, 36, 33, 39, 40, 38, 42, 43, 44, 45, 50, 55, 56, 57, 58, 61, 56, 64, 60, 68, 70, 71, 72, 75, 74, 75, 77, 81, 82, 83, 81, 84, 91, 93, 95, 96, 99, 100, 102, 103, 104, 107, 113, 114, 110, 118, 112, 113, 114, 115, 124, 132, 133, 134, 135, 131, 134, 145, 137, 140, 152, 144, 150, 151, 154, 163, 165, 166, 160, 161, 172, 164, 168, 171, 172, 173, 181, 183, 184, 187, 189, 191, 192, 193, 195, 198, 199, 197};
for (int i = 0; i < num1.length; i++) {
System.out.print(num1[i] + "\t");
}
System.out.println();
for (int i = 0; i < num2.length; i++) {
System.out.print(num2[i] + "\t");
}
System.out.println();
System.out.println(solution.minSwap(num1, num2));
}
}
按照上述代码实现,在时间空间复杂度上比较高,还可以进一步优化,优化后代码如下:
class Solution {
public int minSwap(int[] nums1, int[] nums2) {
int f0 = 0;
int f1 = 1;
int ff0 = 0;
int ff1 = 1;
for (int i = 1; i < nums1.length; i++) {
if ((nums1[i - 1] < nums1[i] && nums2[i - 1] < nums2[i])
&& (nums1[i - 1] < nums2[i] && nums2[i - 1] < nums1[i])) {
ff0 = Math.min(f0, f1);
ff1 = Math.min(f0, f1) + 1;
f0 = ff0;
f1 = ff1;
} else if (nums1[i - 1] < nums1[i] && nums2[i - 1] < nums2[i]) {
ff0 = f0;
ff1 = f1 + 1;
f0 = ff0;
f1 = ff1;
} else if (nums1[i - 1] < nums2[i] && nums2[i - 1] < nums1[i]) {
ff0 = f1;
ff1 = f0 + 1;
f0 = ff0;
f1 = ff1;
} else {
throw new RuntimeException("not supported");
}
}
return Math.min(f0, f1);
}
public static void main(String[] args) {
Solution solution = new Solution();
// System.out.println(solution.minSwap(new int[]{1, 3, 5, 4}, new int[]{1, 2, 3, 7}));
// System.out.println(solution.minSwap(new int[]{3,3,8,9,10}, new int[]{1,7,4,6,8}));
int num1[] = new int[]{1, 8, 4, 6, 7, 8, 16, 18, 19, 29, 25, 26, 35, 31, 38, 35, 37, 41, 39, 43, 48, 49, 46, 47, 50, 52, 54, 55, 63, 58, 67, 63, 69, 71, 74, 73, 76, 77, 80, 78, 79, 80, 86, 87, 90, 93, 95, 96, 97, 100, 101, 105, 106, 108, 108, 109, 116, 111, 119, 121, 122, 124, 130, 125, 126, 127, 128, 140, 144, 135, 148, 151, 143, 154, 155, 157, 160, 156, 158, 159, 168, 170, 163, 173, 175, 176, 177, 180, 177, 182, 183, 184, 185, 190, 191, 194, 194, 195, 196, 200};
int num2[] = new int[]{7, 3, 12, 14, 19, 22, 24, 26, 27, 21, 30, 31, 28, 36, 33, 39, 40, 38, 42, 43, 44, 45, 50, 55, 56, 57, 58, 61, 56, 64, 60, 68, 70, 71, 72, 75, 74, 75, 77, 81, 82, 83, 81, 84, 91, 93, 95, 96, 99, 100, 102, 103, 104, 107, 113, 114, 110, 118, 112, 113, 114, 115, 124, 132, 133, 134, 135, 131, 134, 145, 137, 140, 152, 144, 150, 151, 154, 163, 165, 166, 160, 161, 172, 164, 168, 171, 172, 173, 181, 183, 184, 187, 189, 191, 192, 193, 195, 198, 199, 197};
for (int i = 0; i < num1.length; i++) {
System.out.print(num1[i] + "\t");
}
System.out.println();
for (int i = 0; i < num2.length; i++) {
System.out.print(num2[i] + "\t");
}
System.out.println();
System.out.println(solution.minSwap(num1, num2));
}
}
总结
这道题是一道动态规划的题目,总体感觉这种题目看是否能想到公式,并且考虑完整的case,之后问题就迎刃而解。如果有更加高效简洁的方案欢迎回复。