给出一个二进制数组,找到将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),但答案并未给出正确的输出。
答案 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