801. Minimum Swaps To Make Sequences Increasing

1题目理解

输入:两个int数组A和B,长度都不为0,并且长度相同。
输出:最小交换次数。
规则:最终想要得到两个严格递增的数组。如果原始数组不符合要求,可以在相同的位置交换A、B数组元素。也就是说可以交换A[i]和B[i],使得数组严格递增。并且题目可以保证输入的数组是有效的数组。
例子:
Input: A = [1,3,5,4], B = [1,2,3,7]
Output: 1
Explanation:
交换 A[3] and B[3]得到的序列是:
A = [1, 3, 5, 7] and B = [1, 2, 3, 4]
它们都是严格递增的.

2 暴力搜索

这道题目一眼是看不出递归方程的,所以只能从暴力搜索开始。
我们每次比较第i位元素:如果 A[i]<=A[i-1] 或者 B[i]<=B[i-1] ,那这个时候不符合条件,是一定要交换A[i]和B[i]的。其他情况下,A[i]和B[i]可以交换也可以不交换。当i=0的时候,A[i]和B[i]也是可以交换也可以不交换。
一直比较到数组长度的时候,记录最小交换次数。
因为每个位置都有2种选择,所以时间复杂度是 O ( n 2 ) O(n^2) O(n2)

class Solution {
    private int result;
    public int minSwap(int[] A, int[] B) {
        result = A.length;
         minSwap(A,B,0,0);
        return result;
    }
    private void minSwap(int[] A ,int[] B,int index,int swapCount){
        if(index >= A.length){
            result = Math.min(result,swapCount);
        }else{
            if(index >0 && (A[index]<=A[index-1] || B[index]<=B[index-1])){
            //必须换
                swap(A,B,index);
                if(A[index]<=A[index-1] || B[index]<=B[index-1]){
                    swap(A,B,index);  
                    return;
                }
                minSwap(A,B,index+1,swapCount+1);
                swap(A,B,index);                
            }else{
                minSwap(A,B,index+1,swapCount);
                swap(A,B,index);
                if(index>0 && (A[index]<=A[index-1] || B[index]<=B[index-1])){
                    swap(A,B,index);
                    return;
                }
                minSwap(A,B,index+1,swapCount+1);
                swap(A,B,index);
            }
        }
    }
    
    private void swap(int[] A,int[]B,int index){
        int t = A[index];
        A[index] =  B[index];
        B[index] = t;
    }
}

当这样写完代码之后提交肯定超时。但是根据这个却不知道怎么写递归方程。

3 动态规划

既然根据暴力找不到方程,那就再分析。严格递增是A[i]>A[i-1],所以在考虑第i步的最小交换次数的时候,只需要考虑第i-1步的最小交换次数以及大小关系。
我们令keep[i]表示从0到i是严格递增序列需要交换的最少次数,并且A[i]和B[i]不交换。令swap[i]表示从0到i是严格递增序列需要交换的最少次数,并且A[i]和B[i]交换。
在例子中
1 3 5
1 2 3

3.1第一种情况

当i=2的时候,A[i]>A[i-1] 并且B[i]>B[i-1],在这种状态下A[i]、B[i]可以交换也可以不交换。
如果A[i]、B[i]不交换,那A[i-1]、B[i-1]也应该不换。如果一换的话可能就不是严格递增子序列了。例如3和2换了,5和3不换,那序列变为1 2 5和 1 3 3。这样是不符合要求的。所以keep[i]=keep[i-1],
如果A[i]、B[i]交换,那A[i-1]、B[i-1]也应该交换。例如5和3换了,3和2不换,那序列变为1 3 3和1 2 5。不符合要求。所以swap[i] = swap[i-1]+1。

3.2第二种情况

我们再考虑A[i]和B[i-1]的关系。如果A[i]>B[i-1]并且B[i]>B[i-1]。
在例子中
1 3 5 4
1 2 3 7
在当i=3的时候,就符合这种情形。我们同样考虑A[i]、B[i]交换,不交换两种情况。
如果A[i]、B[i]不交换,那么A[i-1]、B[i-1]应该交换。如果不交换是可能不符合要求的。例子中5和3不交换,4和7也不交换,那结果不符合要求。所以keep[i] = swap[i-1]。
如果A[i]、B[i]交换,那A[i-1]、B[i-1]应该不交换。同样换一下,不符合要求(1 3 3 7,1 2 5 4)我们只比较最后两位。所以swap[i] = keep[i] + 1。

接着考虑A[i]>A[i-1] 并且B[i]>B[i-1] 和 A[i]>B[i-1]并且B[i]>A[i-1]应该是可能同时出现。所以在考虑第二种情况下的计算式的时候,需要改变一下。keep[i] = min(keep[i],swap[i-1]) , swap[i] = min(swap[i],keep[i] + 1)。

题目思路来源于花花酱

开始写代码吧。

class Solution {
    private int result;
    public int minSwap(int[] A, int[] B) {
        int n = A.length;
        int[] swap = new int[n];
        int[] keep = new int[n];
        swap[0] = 1;
        for(int i = 1;i<n;i++){
            swap[i] = n;
            keep[i] = n;
            if(A[i] > A[i-1] && B[i] > B[i-1]){
                keep[i] = keep[i-1];
                swap[i] = swap[i-1] + 1;
            }
            if(A[i]>B[i-1] && B[i]>A[i-1]){
                keep[i] = Math.min(keep[i],swap[i-1]);
                swap[i]  =  Math.min(swap[i],keep[i-1]+1);
            }
        }
        return  Math.min(swap[n-1],keep[n-1]);
    }
    
}

时间复杂度O(n)。空间复杂度可以优化为O(1)。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值