1

I need to design an algorithm which will sort an array which contains numbers -1,0,1 only, without using any temp variable or array and by using only swapping I have come up with the following method I'm not sure if it is 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]);
    }
}
oguz ismail
  • 1
  • 16
  • 47
  • 69
JKLM
  • 1,470
  • 3
  • 28
  • 66
  • Please note that this is _not_ bubble sorting, since bubble sorting needs a comparison against all succeeding elements and thus is quadratic in runtime. – Thomas Lang Apr 03 '19 at 05:22
  • 4
    Maybe you just count the number of -1s, 0s and 1. Then reproduce an array with the correct number of each starting at -1 first.. – drescherjm Apr 03 '19 at 05:23
  • I dont need any specific algorithm I just need to verify complexity of the algorithm I wrote – JKLM Apr 03 '19 at 05:23
  • 3
    [Dutch national flag problem](https://en.wikipedia.org/wiki/Dutch_national_flag_problem) – Blastfurnace Apr 03 '19 at 05:45

2 Answers2

5

The algorithm is definitely not O(n).
You are setting i to 0 when you do a swap. At worst, it is O(n^2).

R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • is it possible to improve it to O(n)? – JKLM Apr 03 '19 at 05:26
  • 1
    it is definitely possible to do it in O(n), you can check out how quicksort works, it can give you a general idea – Ap31 Apr 03 '19 at 05:28
  • 1
    @JKLM, I don't know of any sorting algorithm that can perform better than O(N.log(N)). If there is any, I will be glad to educate myself. – R Sahu Apr 03 '19 at 05:28
  • 2
    the trick is, with elements only being of 3 different values, it's more of a "partition" than a "sort" – Ap31 Apr 03 '19 at 05:29
  • radix sort maybe? – Afshin Apr 03 '19 at 05:30
  • @Afshin the main limitation is I need to use only swapping I'm not sure about counting sort – JKLM Apr 03 '19 at 05:30
  • @RSahu what about using binary search to insert an item at specific place in a linked list? While the last item has a cost of `log(n)`, the item before that has a cost of `log(n-1)` and so on, for a total cost lower than `O(n.log(n))`. Or am I misunderstanding the big O notation? – Ferrybig Apr 03 '19 at 06:34
1

The reason why your algorithm has been stated correctly by @RSahu, you are resetting the counter to 0 which means you can do as much as 1+2+...+n iterations.

Here is a small example exhibiting linear time to process the array:

#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;
}

You can see it live there.

How does it work ? We maintain three counters i, j and k with the invariants that:

  • all items in the range: [0, i) are -1
  • all items in the range: [i, j) are 0
  • all items in the range: (k, n-1) are +1

Where [ means an inclusive bound, and ) or ( means an exclusive bound.

Initially

i=j=0 and 'k=n-1`. The invariants are respected.

First case

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

The value of A[j] is 0, so we can increment j and the invariants still hold.

Second case

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

As i is an exclusive bound, we are adding a -1 to the previous range of -1 and the increment of i is needed. If the range [i, j) was not empty, a 0 has been copied to position j and we must increment j. If the range was empty, then we had i==j, and as we increment i we must also increment j to keep the invariant. We can conclude that the invariants still hold after this step.

Third case

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

A[j] is 0 we can swap it with the value at A[k] and decrement k and the invariants will hold.

Termination and correctness

The final point is proving the program will terminate. Each step either: - increment j - decrement k So the distance between j and k will decrease by 1 every step.

The distance between j and k is initially n-1, and decreases by one every step. So there will be at most n-1 steps. Each step does one swap. There will be at most n-1 swaps.

At the end of the program the invariants will hold:

  • from 0 to i excluded, all -1
  • from i to j==k excluded, all 0
  • from j==k to n-1 excluded, all +1
fjardon
  • 7,921
  • 22
  • 31