4

The Question: Consider the problem of sorting n items, where the comparison oracle, in the execution of an algorithm, is allowed to lie at most once. Complexity is measured in terms of the number of comparisons (oracle consultations) used. Show how to sort n items in this model using only nlgn +O(n) comparisons, giving your algorithm and proof of correctness.

What I've got:

My best solution so far is pretty rudimentary. I'm basically implementing a form of merge sort, where the only difference is, when comparing to merge, I compare twice (since the oracle can only lie once if there is an inconsistency I will compare a third time but this can only happen once).

I know that there are lg(n) levels of merges, and that since I have n elements, the maximum amount of comparisons I will make is 2nlg(n)+1. However this is a rather crude upper bound as I know that a merge of two arrays of length m and p takes m+p-1 comparisons (and not m+p).

For simplicity, if I assume array lengths are powers of 2, I have that m=p, and I get a total of n-1 merges. So I can subtract 2(n-1) from 2nlg(n)+1 which gives me 2nlg(n) - 2n - 1 comparisons.

Not quite the answer I am looking for. I think I am going about it the wrong way (I don't think it is necessary for me to compare twice every time I merge..) and I would be very grateful if anyone could push me in the right direction!

Cheers,

Sacha

1 Answers1

1

My solution:

(Assuming I am sorting numbers in increasing order for simplicity of language).

1) I do MergeSort as usual (there is a maximum of one error in my array)

2) I go through the array comparing each index twice to the next one (and perhaps a third time once if the results of the comparison are inconsistent)

3) If A[i] > A[i+1] (confirmed twice by the oracle), I've found my error, switch A[i+1] and A[i], check if A[i+1]>A[i+2], if this is the case, go up the array comparing A[i+1] with A[i+2] twice (worst case) and so on (until i reaches n-2). At each stage switching A[i+1] and A[i+2] if A[i+1]>A[i+2]. If A[i+1]<=A[i+2], go backwards down the array comparing A[i] with A[i-1] twice (worst case) and so on (until i reaches 0). At each stage switching A[i] and A[i-1] if A[i]>A[i-1].

Step 1 will result in less than nlgn comparisons, and steps 2 and 3 a maximum of 4n+1 comparisons.

Of course all this needs to be formalised but I think this is the basic idea.

Please don't hesitate to let me know if I am missing something or am completely mistaken here.

Thanks,

Sacha

  • Why do you go downwards? – Justin D. Jan 21 '14 at 19:50
  • @JustinD. thanks for pointing that out! I've think I've corrected it now. – Sacha Saint-Leger Jan 21 '14 at 21:32
  • Actually, I think you were right... If you try a merge sort with the array [26 1 2 3 4 5 6 8 7], making the error 1 > 26, you'll get the final array [2 3 4 5 6 7 8 26 1]. All the numbers before the error are in correct order (and probably also after). You have to find where to place [26 1]. PS: are you at McGill, 252? – Justin D. Jan 21 '14 at 21:43
  • yes, but let's say after merge sort I end up with something like [1 2 3 4 5 8 6 7]? is that possible? – Sacha Saint-Leger Jan 21 '14 at 21:47
  • I tried with [10 1 2 3 4 6 5 8 15 12 9 8], the oracle error being 10 < 1. Merge sort gives [2 3 4 5 6 8 8 9 10 1 12 15]. So the 10 was placed appropriately, but because of the way `merge` operates, the 1 was misplaced. So after merge sort, scan the array to find the error and move the second element to its appropriate place ; worst-case is `n`. A binary search for that element and then insert would give `log n + n` in the worst case. – Justin D. Jan 21 '14 at 21:49
  • I don't think your `[1 2 3 4 5 8 6 7]` is possible. In the `merge` phase, 8 will be compared to 7 and will be placed before. I think there can only be one misplaced number in the array. – Justin D. Jan 21 '14 at 21:51