【数组】使序列递增的最小交换次数

题目描述

我们有两个长度相等且不为空的整型数组 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,之后问题就迎刃而解。如果有更加高效简洁的方案欢迎回复。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值