二进制数组的最小相邻交换数

时间:2019-07-03 22:50:43

标签: java algorithm

给出一个二进制数组,找到将1和0分组所需的最小相邻交换数。

示例:

Input : 0,1,0,1 (array with 0 based index)
Swaps needed : 0,1,0,1 -> 0,0,1,1 (1 swap from index 1 to index 2)

Solution : 1

示例:

Input : 1,0,1,0,0,0,0,1
Swaps needed : 
1,0,1,0,0,0,0,1 -> 1,1,0,0,0,0,0,1 -> 1,1,0,0,0,0,1,0 -> 1,1,0,0,0,1,0,0 -> 1,1,0,0,1,0,0,0 -> 1,1,0,1,0,0,0,0 -> 1,1,1,0,0,0,0,0

Total 6 swaps so the solution is 6.

1和0可以位于开头或结尾,但它们应位于单个位置,即开头或结尾。

针对此要求,我提出了以下逻辑。我在hackerrank中尝试过,因为一个隐藏的测试用例失败了,并且由于我的代码中嵌套了循环,所以给出了3个测试用例的超时时间。

static int countSwaps(List<Integer> list) {
    int temp;
    int swaps = 0;
    int n = list.size();
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n - 1; j++) {
            if ((list.get(j) == 0) && (list.get(j + 1) == 1)) {
                temp = list.get(j);
                list.set(j, list.get(j + 1));
                list.set(j + 1, temp);
                swaps++;
            }
        }
    }

    return swaps;
}

解决此程序的更好方法是什么?

我已经看过这篇文章Given an array of 0 and 1, find minimum no. of swaps to bring all 1s together (only adjacent swaps allowed),但答案并未给出正确的输出。

2 个答案:

答案 0 :(得分:4)

要将所有1移到左侧,令p(i)为第i个1的位置,从左到右。它最终需要移动到位置i。这将需要p(i)-我交换。只需将所有i的数量相加即可。

int countSwaps(int [] a) {
  int n = 0, i = 0;
  for (int p = 0; p < a.length; ++p)
    if (a[p] == 1) {
      n += p - i;
      ++i;
    }
  return n;
}

向右移动是对称的。进行类似的计算并计算最小值。

答案 1 :(得分:1)

answer by Gene为基础,修复了编译错误,并支持将1移至左侧(开始)移至右侧(移至最后),也就是将0移至左侧:

static int countSwaps(int... a) {
    int n0 = 0, i0 = 0, n1 = 0, i1 = 0;
    for (int p = 0; p < a.length; ++p) {
        if (a[p] == 0)
            n0 += p - i0++; // No. of steps to move the 0 to the left
        else
            n1 += p - i1++; // No. of steps to move the 1 to the left
    }
    return Math.min(n0, n1); // Choose lowest no. of steps
}

测试

System.out.println(countSwaps(0,1,0,1));
System.out.println(countSwaps(1,0,1,0,0,0,0,1));
System.out.println(countSwaps(1,0,0,0,0,1,0,1));

输出

1
6
6