布尔数组在O(1)空间和O(n)时间内重新排序

Jih*_*ine 27 java arrays algorithm

问题取自编程访谈要素:

给定具有布尔值键的n个对象的数组A,对数组重新排序,以便首先出现具有错误键的对象.具有键true的对象的相对排序不应更改.使用O(1)额外空间和O(n)时间.

我做了以下操作,它保留了对象为true的对象的相对排序,并使用了O(1)额外空间,但我相信它的时间复杂度为O(n*n!).

public static void rearrangeVariant4(Boolean[] a) {
  int lastFalseIdx = 0;
  for (int i = 0; i < a.length; i++) {
    if (a[i].equals(false)) {
      int falseIdx = i;
      while (falseIdx > lastFalseIdx) {
        swap(a, falseIdx, falseIdx-1);
        falseIdx--;
      }
      lastFalseIdx++;
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

任何人都知道如何在O(n)时间内解决它?

Ben*_*ler 29

boolean array[n]; // The array
int lastTrue = n;
for (int i = n-1; i >= 0; --i) {
  if (array[i]) {
    swap(array[--lastTrue], array[i]);
  }
}
Run Code Online (Sandbox Code Playgroud)

在每次迭代之后lastTrue,所有后面的元素都是真的.没有两个真正的元素被交换,因为如果之间存在真正的元素i,lastTrue那么它已经被遇到并移动到后面lastTrue.这在O(n)时间和O(1)记忆中运行.

  • @Ricky [不要陷入这个陷阱](http://tirania.org/blog/archive/2011/Feb-17.html).在任何情况下,我们都在谈论Java,因此整数(和数组大小)限制为32位,因此假设操作的持续时间和单个数字的内存更加有用和简单. (4认同)
  • OP仅需要保留真值之间的相对排序. (3认同)
  • @Ricky是的,这一切都取决于你想要使用的计算模型.事实证明,对于各种算法,假设单个整数占用O(1)空间,而O(1)时间用于简单的算术运算是最有用的.因此,对于许多问题,假设`reduce(arr,(t,e) - > t + e)`O(n)是完全正常的,尽管是的,你也可以使用O(nm),其中m是位大小 - 对于一些问题,这确实会产生很大的不同. (2认同)
  • 如果减量没有内联,我认为这是一个改进.= /少考虑,减少混乱. (2认同)

Jar*_*ows 7

Java代码 - 如果您使用Boolean[]- 对象:

时间 - O(1),空间 - O(1)

public static <T> void swap(T[] a, int i, int j) {
    T t = a[i];
    a[i] = a[j];
    a[j] = t;
}
Run Code Online (Sandbox Code Playgroud)

时间 - O(N),空间 - O(1)

public static Boolean[] getReorderBoolObjects(Boolean[] array) {
    int lastFalse = 0;

    for (int i = 0; i < array.length; i++) {
        if (!array[i]) {
            swap(array, lastFalse++, i);
        }
    }

    return array;
}
Run Code Online (Sandbox Code Playgroud)

Spock 测试用例:

def "reorder bools - objects"() {
    given:
    Boolean[] b = [false, true, true, true, false, true]

    when:
    getReorderBoolObjects(b)

    then:
    b == [false, false, true, true, true, true]
}
Run Code Online (Sandbox Code Playgroud)

Java代码 - 如果您使用boolean[]- 原语:

时间 - O(N),空间 - O(1)

public static boolean[] getReorderBoolPrimitives(boolean[] array) {
    int falseCount = 0;
    for (final boolean bool : array) {
        if (!bool) {
            falseCount++;
        }
    }
    for (int i = 0; i < array.length; i++) {
        array[i] = i >= falseCount;
    }
    return array;
}
Run Code Online (Sandbox Code Playgroud)

Spock 测试用例:

def "reorder bools - primitives"() {
    given:
    boolean[] b = [false, true, true, true, false, true]

    when:
    getReorderBoolPrimitives(b)

    then:
    b == [false, false, true, true, true, true]
}
Run Code Online (Sandbox Code Playgroud)