在O(n)中排序,没有任何临时变量

时间:2019-04-03 05:20:31

标签: c algorithm sorting

我需要设计一种算法,该算法将对仅包含数字-1,0,1的数组进行排序,而不使用任何临时变量或数组,并且仅使用交换,所以我想出了以下方法:如果是O(n)。

#include <stdio.h>
#define MAXSIZE 10

int main()
{
    int array[MAXSIZE];
    int i, j, num = 8, temp;

    int list[] = {-1,0,-1,0,1,1,0,1};

    int size = sizeof(list)/sizeof(list[0]);
    for (int i = 1; i < size; i++) {

        if (list[i] < list[i - 1]) {
            list[i] = list[i] + list[i - 1];
            list[i - 1] = list[i] - list[i - 1];
            list[i] = list[i] - list[i - 1];
            i = 0;
        }
    }

    printf("Sorted array is...\n");
    for (int i = 0; i < size; i++)
    {
        printf("%d\n", list[i]);
    }
}

2 个答案:

答案 0 :(得分:5)

该算法绝对不是O(n)。
进行交换时,您正在将i设置为0。最坏的情况是O(n ^ 2)。

答案 1 :(得分:1)

@RSahu正确说明了算法的原因是,您将计数器重置为0,这意味着您最多可以进行1+2+...+n次迭代。

这是一个展示线性时间来处理数组的小例子:

#include <iostream>
#include <array>

using namespace std;

int main() {
    array<int,10> A{-1, 0, -1, 0, 1, 1, 0, 1, 0, -1};

    int i=0,j=0, k=9;
    while(j!=k) {
        if(A[j] == 0) {
            ++j;
        }
        else if(A[j] == -1) {
            swap(A[i], A[j]);
            ++i; ++j;
        }
        else {
            swap(A[j], A[k]);
            --k;
        }
    }

    for(auto ai : A)
        cout << ai << " ";
    cout << endl;
}

您可以在线观看there

它如何工作?我们维护三个计数器ijk,它们的不变量为:

  • 以下范围内的所有项目:[0, i)-1
  • 以下范围内的所有项目:[i, j)0
  • 以下范围内的所有项目:(k, n-1)+1

[表示包含范围,而)(表示包含范围。

最初

i=j=0和'k = n-1`。不变式受到尊重。

第一种情况

if(A[j] == 0) {
    ++j;
}

A[j]的值为0,因此我们可以递增j,并且不变式仍然成立。

第二种情况

else if(A[j] == -1) {
    swap(A[i], A[j]);
    ++i; ++j;
}

由于i是排他性约束,因此我们要向-1的先前范围添加-1,并且需要增加i。如果范围[i, j)不为空,则0已复制到位置j,我们必须递增j。如果范围为空,则我们有i==j,并且随着我们增加i,我们还必须增加j来保持不变。我们可以得出结论,在此步骤之后,不变式仍然成立。

第三种情况

else {
    swap(A[j], A[k]);
    --k;
}

A[j]0,我们可以将其交换为A[k]的值并递减k,不变式将成立。

终止和正确性

最后一点是证明程序将终止。每个步骤之一:  -递增j  -递减k 因此,jk之间的距离每步将减少1。

jk之间的距离最初为n-1,并且每步减小一。因此最多将有n-1个步骤。每个步骤执行一次交换。最多会有n-1个交换。

程序结束时,不变式将保持不变:

  • 0i排除,所有-1
  • ij==k排除,所有0
  • j==kn-1排除,所有+1