http://www.techiedelight.com/sort-binary-array-linear-time/
“线性时间”意味着我们只需要遍历一次数组,但是根据这里的解决方案,我们将首先遍历数组以查找零的数量,然后再次遍历它以用零填充数组的第一部分和剩余部分用1填充。
那么这怎么是线性时间的解决方案呢?我错过了什么吗?
http://www.techiedelight.com/sort-binary-array-linear-time/
“线性时间”意味着我们只需要遍历一次数组,但是根据这里的解决方案,我们将首先遍历数组以查找零的数量,然后再次遍历它以用零填充数组的第一部分和剩余部分用1填充。
那么这怎么是线性时间的解决方案呢?我错过了什么吗?
Sort()
中的循环:int zeros = 0;
for (int i = 0; i < n; i++)
if (A[i] == 0)
zeros++;
这个循环线性遍历A[]
,并计算零的数量。这些循环中也应用了线性时间:
int k = 0;
while (zeros--)
A[k++] = 0;
// fill all remaining elements by 1
while (k < n)
A[k++] = 1;
由于您只是简单地遍历了A[]
,所以这些操作组合在一起的时间复杂度为O(2n)
,因为数组被遍历两次。因此,Sort()
函数是一个O(2 * n)
的操作,相当于O(n)
。
以下是另一个例子。如果你需要对比10个二进制数和100个二进制数进行排序,哪一个需要更多的时间?在这种情况下,对100个二进制数进行排序将比对10个二进制数进行排序长10倍。这是因为线性时间与输入大小n
成正比增加。
如果算法的时间复杂度为O(n),则称其为线性时间或O(n)时间。简单来说,这意味着对于足够大的输入大小,运行时间与输入大小成线性增长。
由于此算法遍历数组两次,因此仍然是线性的。可以将其想象成一个线性方程y = 2*x。
O(n)
。但是直接或间接地它们会两次遍历数组中的相同元素,而 Aquarius(提问者)正在寻找一次遍历的方法。下面的代码在遍历数组时对其进行排序并仅遍历一次。int left = 0, right = arr.length - 1;
while (left < right)
{
while (arr[left] == 0 && left < right)
left++;
while (arr[right] == 1 && left < right)
right--;
if (left < right)
{
arr[left] = 0;
arr[right] = 1;
left++;
right--;
}
}
记录一下,
O(c*n) = O(n),其中c为常数
O(2n) = O(n)
。大O符号忽略常数。 n
和 2n
都随着 n
的值线性增长。将一个常数乘以或加到一个函数中不会改变函数的行为。O(2n), O(1221n), O(n), O(n/2)。所有这些都是线性的。这意味着执行时间始终会不断变化。因此,如果您有一个大小为10的数组,它将始终比对大小为5的数组进行排序需要花费两倍的时间。