【问题标题】:Sorting in O(n) without any temp variable在没有任何临时变量的情况下以 O(n) 排序
【发布时间】:2019-08-24 12:50:15
【问题描述】:

我需要设计一种算法来对仅包含数字 -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]);
    }
}

【问题讨论】:

  • 请注意,这不是冒泡排序,因为冒泡排序需要与所有后续元素进行比较,因此在运行时是二次的。
  • 也许你只计算 -1、0 和 1 的数量。然后首先从 -1 开始重新生成每个正确数量的数组..
  • 我不需要任何特定的算法我只需要验证我写的算法的复杂性

标签: c algorithm sorting


【解决方案1】:

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

【讨论】:

  • 是否可以提高到O(n)?
  • 绝对可以在O(n)内完成,你可以看看快速排序是如何工作的,它可以给你一个大概的思路
  • @JKLM,我不知道任何排序算法可以比 O(N.log(N)) 执行得更好。如果有的话,我会很高兴自学。
  • 诀窍在于,元素只有 3 个不同的值,它更像是一个“分区”而不是“排序”
  • 基数排序可能吗?
【解决方案2】:

@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

【讨论】:

  • 谢谢@fjardon
猜你喜欢
  • 1970-01-01
  • 2011-06-02
  • 1970-01-01
  • 2012-09-30
  • 1970-01-01
  • 1970-01-01
  • 2015-03-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多