相对交换两个数组的最小交换量

时间:2018-08-03 15:22:51

标签: arrays algorithm sorting

给定两个数组arr1arr2,我们必须找到最小交换量,以将两个数组按严格递增的顺序进行相对排序。如果无法进行相对排序,则返回-1。

相对排序定义为交换arr1arr2的相同索引元素。

即相对排序步骤:

swap(arr1[i], arr2[i])

严格将升序定义为:

arr[i+1]>arr[i] for all i

示例:

arr1={1,4,4,9} 
arr2={2,3,5,10}

则最小交换为1,因为交换arr1[2]arr2[2]将使两个数组都严格增加。 我使用递归解决了这个问题。 如果为arr[i]>arr[i+1],我们可以交换索引为i的元素或索引为i+1的元素,然后调用索引为i+1的函数。我试图找到两个值中的最小值并返回它。 i的每个索引都遵循此过程。

int f(int N, int *arr1, int *arr2, int i){
    if(i == N-1)
        return 0;
     if(arr1[i]>=arr1[i+1] && arr2[i]>=arr2[i+1])return -1;
    if(arr1[i]>=arr1[i+1] || arr2[i]>=arr2[i+1]){
        int m, n;
        swap(arr1[i], arr2[i]);
        m = f(N, arr1, arr2, i+1);
        swap(arr1[i], arr2[i]);
        swap(arr1[i+1, arr2[i+1]);
        n = f(N, arr1, arr2, i+1);
        if(m == -1 && n==-1)return -1;
        if(m==-1)return n;
        if(n==-1)return m;
        return min(m, n);
    }
    return f(N, arr1, arr2, i+1);
 }

int minSwaps(int N, int *arr1, int *arr2){
    return f(N, arr1, arr2, 0);
}

由于这是我在在线编码测试中遇到的一个问题,因此我通过了基本测试用例,但是我仍然不确定该方法是否适用于所有测试用例。

此外,我想知道是否可以使用动态编程解决此问题。如果是,应在表中存储什么状态?那应该怎么做?

2 个答案:

答案 0 :(得分:1)

您的解决方案的数组大小是指数的。正如您在问题中注意到的那样,可以使用动态编程来获得解决方案。

首先,让我们定义一个辅助函数,该函数检查交换i-th and/or i + 1-st元素后是否获得本地有效的解决方案。我在本地有效的意思是仅考虑这四个数字。

def isValid(i, preSwap, postSwap):
  val lx = if (preSwap) y(i) else x(i)
  val rx = if (postSwap) y(i + 1) else x(i + 1)
  val ly = if (preSwap) x(i) else y(i)
  val ry = if (postSwap) x(i + 1) else y(i + 1)
  // x(i) < x(i + 1) && y(i) < y(i + 1)
  lx < rx && ly < ry

现在,我们将简单地向后循环数组。我们的动态编程内存将是恒定的-我们只需要记住两个整数。让我们考虑i-th的{​​{1}}迭代。

  • 什么是最佳交换数量,以便使索引i = x.length - 2 downto 0越来越多地排序,并且{strong>不交换i + 1 upto x.length - 1x(i)
  • 交换的最佳数量是多少,以使索引y(i)的排序越来越多,而{strong>交换了i + 1 upto x.length - 1x(i)

对于长度为y(i)的列表,我们获得一个元组1。我们的循环步骤将考虑四种情况:

  • 我们不在(prevNoSwap, prevSwap) = (0, 1)交换,也不会在i交换;最佳:i + 1
  • 我们在prevNoSwap交换,我们不在i交换;最佳:i + 1
  • 我们不在prevNoSwap + 1交换,而在i交换;最佳:i + 1
  • 我们在prevSwap交换,我们不在i交换;最佳:i + 1

如果给定的情况创建了有效的解决方案,我们将其视为可能的步骤数。我们将它们按prevSwap + 1的{​​{1}}分组,并取最小值。我们假定,如果在特定情况下找不到解决方案,那么任何这些元素都可能成为swapping / not swapping

循环后,我们至少选择两个元组值。这是其余的伪代码:

i

答案 1 :(得分:0)

int minSwap(vector<int>& a, vector<int>& b){
    int inf = (int)(1e9);
    int n=a.size();
    int dp[n][2];
    dp[0][0]=0;
    dp[0][1]=1;
    for(int i=1;i<n;i++)
        dp[i][0]=dp[i][1]=inf;
    for(int i=1;i<n;i++){
        if(a[i-1]<a[i]&&b[i-1]<b[i]){
            dp[i][0]=dp[i-1][0];
            dp[i][1]=dp[i-1][1]+1;
        }
        if(a[i-1]<b[i]&&b[i-1]<a[i]){
            dp[i][0]=min(dp[i][0],dp[i-1][1]);
            dp[i][1]=min(dp[i][1],dp[i-1][0]+1);
        }
    }
    return min(dp[n-1][0],dp[n-1][1]);
}