假设我有一个数组[1、2、4、5、3]。在此数组中,如果要对数组进行排序,则3、4和5不会处于它们应处于的位置。如何检查有多少元素不在正确的位置?
我能想到的最快方法是将值复制到临时数组,对数组进行排序,然后比较哪些索引具有不同的值。那将是一个O(nlogn)解决方案。在O(n)中有什么方法可以做到吗?
答案 0 :(得分:3)
那将是一个O(nlogn)解决方案。在O(n)中有什么方法可以做到吗?
否。
这是一个非正式证明。
假设存在一种算法A
,该算法可以发现数组中所有位置不正确的元素都比O(nlogn)
好。还要假设A
告诉您每个元素的正确位置是什么。这意味着您可以按以下方式对数组进行排序:
list_of_moves = A(array);
for move in list_of_moves:
apply move
(这里有一个故意的“手浪”,因为移动不是简单的交换。但是在O(m)
中有简单的算法可以做到这一点。例如,考虑“时钟耐心”。)
我们认为A
是O(n)
。移动步骤也将是O(m)
,其中m
是移动数...,小于或等于n
。因此,我们现在有一个 general 排序算法,即O(n + m)
。那是与O(n)
相同的复杂度类。
但是,有数学证明O(nlogn)
是常规排序算法的下界。 (有关证明的说明,请参见https://www.bowdoin.edu/~ltoma/teaching/cs231/spring14/Lectures/6-moresorting/sortLB.pdf。)
矛盾!
因此,具有这些属性A
的算法O(n)
。
另一种选择是,(假设的)算法A
会(准确地)告诉您哪些元素位于错误的位置,而不是它们的正确位置。
我认为这也是不可能的,但是我现在没有证据。
请注意,这与检查元素是否有序不同。这在O(n)
中很容易做到。
问题在于,乱序元素仍然可以位于正确的位置。例如:
1, 4, 3, 2
3乱序,但位置正确。在完全排序的数组中,3将处于现在的位置。 2和4将被切换。
答案 1 :(得分:-1)
您可以进行for循环,并检查下一个数组索引值是否大于之前的值。
int x = 0;
for (int i = 0; i < array.length - 1; i++)
{
if (array[i+1] > array [i])
{
x++;
}
}
x将是不按顺序排列的元素数