如果给出一个1和0的数组,那么显示将所有1组合在一起所需的最小相邻交换数的好算法。 1不需要在数组中的任何特定位置进行分组。它们只需要分组到最小数量的相邻交换的任何地方。
例如,如果数组看起来像这样......
1,0,0,1,1,0,1
...相邻互换的最小数量为3,因为您将以索引4为中心并进行以下互换:
交换索引0和1,结果是:
0,1,0,1,1,0,1
交换索引1和2,导致:
0,0,1,1,1,0,1
交换索引5和6,导致:
0,0,1,1,1,1,0
任何人都有一个很好的算法来查找1和0的任何数组的最小相邻互换数量?
答案 0 :(得分:2)
更新:
算法通过获取1的所有索引的数组来确定中心。该数组的中心始终保持中心索引。快得多。
oneIndices = array of indices of all 1's in the input
middleOfOnesIndices = round(oneIndices.length/2)-1 // index to the center index
minimumSwaps = 0
foreach index i of oneIndices
minimumSwaps += aboluteValue(oneIndices[middleOfOneIndices]-oneIndices[i])-absoluteValue(middleOfOneIndices-i);
这是一个在行动中看到它的小提琴:
https://jsfiddle.net/3pmwrk0d/6/
这是一个有趣的。谢谢你的问题。
答案 1 :(得分:0)
这是一个简单但不是非常聪明的算法,可以对[0,255]范围内的任何输入执行穷举搜索。
var transition = [],
isSolution = [];
function init() {
var msk = [ 3, 6, 12, 24, 48, 96, 192 ],
i, j, n, x, cnt, lsb, msb, sz = [];
for(i = 0; i < 0x100; i++) {
for(n = cnt = msb = 0, lsb = 8; n < 8; n++) {
if(i & (1 << n)) {
cnt++;
lsb = Math.min(lsb, n);
msb = Math.max(msb, n);
}
}
sz[i] = msb - lsb;
isSolution[i] = (sz[i] == cnt - 1);
}
for(i = 0; i < 0x100; i++) {
for(j = 0, transition[i] = []; j < 0x100; j++) {
x = i ^ j;
if(msk.indexOf(x) != -1 && (x & i) != x && (x & j) != x && sz[j] <= sz[i]) {
transition[i].push(j);
}
}
}
}
function solve() {
var x = parseInt(document.getElementById('bin').value, 2),
path = [ x ],
list = [],
i, min, sol = [], res = [];
recurse(x, path, list);
for(i in list) {
if(min === undefined || list[i].length <= min) {
min = list[i].length;
(sol[min] = (sol[min] || [])).push(list[i]);
}
}
console.log('Optimal length: ' + (min - 1) + ' step(s)');
console.log('Number of optimal solutions: ' + sol[min].length);
console.log('Example:');
for(i in sol[min][0]) {
res.push(('0000000' + sol[min][0][i].toString(2)).substr(-8, 8));
}
console.log(res.join(' -> '));
}
function recurse(x, path, list) {
if(isSolution[x]) {
list.push(path);
return;
}
for(i in transition[x]) {
if(path.indexOf(y = transition[x][i]) == -1) {
recurse(y, path.slice().concat(y), list);
}
}
}
init();
<input id="bin" maxlength="8" placeholder="enter binary string">
<button onclick="solve()">solve</button>
答案 2 :(得分:0)
嗨,首先我想建议相邻交换的最小数量对于给定的示例而言是2而不是3.因为只需将索引2交换为索引2.因此,从左侧交换1次,从右。强>
这是我找到最小交换以使数组以连续1的形式出现的方法 -
步骤1:首先找到连续1的最大数量的中心索引 步骤2:解析数组的左侧以交换它并以有效的方式计算交换次数(不要不必要地交换) 步骤3:对右侧阵列执行相同操作 第4步:加上双方的数量。
请根据相同的策略查看我的java程序:
prn-str
} `
我对表现不太确定。但据我所知,这应该不是低效的。如果有人发现任何性能问题,请告诉我:)
答案 3 :(得分:0)
方法: 这可以通过在每个1的右侧找到零的数目并将其相加来完成。为了对数组进行排序,每个人总是必须在其右边的每个零处执行交换操作。
因此,数组中特定1的交换操作总数是其右侧的零数。找出每一个右边的零的数目,即交换的数目,并将它们全部相加以获得交换的总数。
// Java代码以查找用于对二进制数组进行排序的最小交换次数
class MinimumNumberOfSwapsNeeded {
static int findMinSwaps(int arr[], int n)
{
// Array to store count of zeroes
int noOfZeroes[] = new int[n];
int i, count = 0;
// Count number of zeroes
// on right side of every one.
noOfZeroes[n - 1] = 1 - arr[n - 1];
for (i = n - 2; i >= 0; i--)
{
noOfZeroes[i] = noOfZeroes[i + 1];
if (arr[i] == 0)
noOfZeroes[i]++;
}
// Count total number of swaps by adding number
// of zeroes on right side of every one.
for (i = 0; i < n; i++)
{
if (arr[i] == 1)
count += noOfZeroes[i];
}
return count;
}
// Driver Code
public static void main(String args[])
{
int ar[] = { 0, 0, 1, 0, 1, 0, 1, 1 };
System.out.println(findMinSwaps(ar, ar.length));
}
}
答案 4 :(得分:0)
** 将 0 和 1 的数组分组,以便可以在 O(2*n) ~ O(n) 复杂度中计算最小交换。**
package com.segregate.array;
import java.util.ArrayList;
import java.util.List;
public class ArraySegregation {
public static void main(String[] args) {
List<Integer> arr = new ArrayList<>();
/*
*
* List -> low high [1 1 0 0 1 0] -> [ 000111] or [111000]
*
* 1 1 0 0 1 0 -> 000111
*/
arr.add(0);
arr.add(0);
arr.add(0);
arr.add(1);
arr.add(1);
arr.add(0);
arr.add(1);
arr.add(0);
arr.add(0);
List<Integer> arr1 = new ArrayList<>(arr);
int low = 0, high = arr.size() - 1;
int counter1 = 0, counter2 = 0;
// case for swaps such that all 0 in the left side.
while (low < high) {
switch (arr.get(low)) {
case 0:
while (arr.get(low) == 0)
low++;
break;
case 1:
while (arr.get(high) == 1)
high--;
swap(low, high, arr);
counter1++;
high--;
low++;
break;
}
}
// case for swaps such that all 0 in the right side.
/*
* [1 1 0 0 1 0] -> 11 1 0 0 0
*
*
*/
low=0;high = arr1.size() - 1;
while (low < high) {
switch (arr1.get(low)) {
case 0:
while (arr1.get(high) == 0)
high--;
swap(low, high, arr1);
counter2++;
high--;
low++;
break;
case 1:
while (arr1.get(low) == 1)
low++;
break;
}
}
int count = (counter1 > counter2) ? counter2 : counter1;
System.out.println(count);
}
private static void swap(int low, int high, List<Integer> arr) {
int temp1 = 0;
temp1 = arr.get(low);// 1
arr.remove(low);
arr.add(low, arr.get(high-1));
arr.remove(high-1);
arr.add(high, temp1);
}
}