给定0和1的数组,找到最小数量。交换将所有1组合在一起(仅允许相邻的交换)

时间:2016-08-03 16:12:02

标签: arrays algorithm sorting

如果给出一个1和0的数组,那么显示将所有1组合在一起所需的最小相邻交换数的好算法。 1不需要在数组中的任何特定位置进行分组。它们只需要分组到最小数量的相邻交换的任何地方。

例如,如果数组看起来像这样......

1,0,0,1,1,0,1

...相邻互换的最小数量为3,因为您将以索引4为中心并进行以下互换:

  1. 交换索引0和1,结果是: 0,1,0,1,1,0,1

  2. 交换索引1和2,导致: 0,0,1,1,1,0,1

  3. 交换索引5和6,导致: 0,0,1,1,1,1,0

  4. 任何人都有一个很好的算法来查找1和0的任何数组的最小相邻互换数量?

5 个答案:

答案 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);
    }
}