-5

Can someone explain why the in next permutation algorithm, we have O(n) as worst case and O(1) as best case? An explanation with an example would be appreciated...

The algorithm is:

  1. Find the largest index k such that a[k] < a[k + 1]. If no such index exists, the permutation is the last permutation.

  2. Find the largest index l greater than k such that a[k] < a[l].

  3. Swap the value of a[k] with that of a[l].

  4. Reverse the sequence from a[k + 1] up to and including the final element a[n].

I'm new to learning algorithms. So, it's a bit difficult for me to "visualize" the worst and best case of this algorithm in my head. Thanks.

qfwfq
  • 2,416
  • 1
  • 17
  • 30
mskeira
  • 25
  • 1
  • 5
  • 1
    **Which** next permutation algorithm? If you write out the algorithm, does it become obvious what the answer to your question is? If you don't, how are we ti know what algorithm you refer to? – rici Sep 10 '16 at 15:04
  • Are you refering to [this part](https://en.wikipedia.org/wiki/Permutation#Generation_in_lexicographic_order) in the Wikipedia article? – ayhan Sep 10 '16 at 15:42
  • @ayhan: yes, that's what I'm referring to. – mskeira Sep 10 '16 at 15:51

1 Answers1

0

The reason it is in O(n) is that you must find two specific characters. In general, if an algorithm relies on you finding a specific thing out of a list of n things the algorithm will be in O(n) but will be constant time in the best case. To help with visualizing it let's trace the algorithm on a couple strings.

Worst Case

Consider finding the next permutation given the string

a = 6 7 5 4 3 2 1

We must first find the rightmost character that is less than the character right after it. To do this we can search backwards through the string:

6 7 5 4 3 2 1

6 7 5 4 3 2 1

6 7 5 4 3 2 1

6 7 5 4 3 2 1

6 7 5 4 3 2 1

6 7 5 4 3 2 1 Found it!

That took 6 comparisons. Let's call the left index k, giving us k=0. Now you have to find the rightmost character that is greater than k. We can again do this by looking backwards through the list.

6 7 5 4 3 2 1

6 7 5 4 3 2 1

6 7 5 4 3 2 1

6 7 5 4 3 2 1

6 7 5 4 3 2 1

6 7 5 4 3 2 1 Found it!

That took 6 comparisons. Let's call that index l, giving us k=0 and l=1. Now, swap the two values.

6 7 5 4 3 2 1 --> 7 6 5 4 3 2 1

And now reverse the sequence from k+1 up to the end of the list. I am not going to write this out because I do not think it is particularly important to understanding the algorithm, but not that this is not a constant time operation. If you are using an array, reversing the elements would be linear. This does not change the efficiency class.

7 6 5 4 3 2 1 --> 7 1 2 3 4 5 6

And you have the next permutation! I don't think it is hard to see that this is the worst case scenario. This took 6 + 6 = 12 comparisons, which is equal to 2 * (length(a) - 1). If we expand this we get 2 * length(a) - 2. Both of the 2's can be dropped because we don't care about constant addition or multiplication in big-O and we are left length(a), putting the algorithm in O(n).


Best Case

Now let's look at the (much shorter) best case.

a = 1 2 3 4 5 6 7

Find k

1 2 3 4 5 6 7 Found it!

Find l

1 2 3 4 5 6 7 Found it!

Swap k and l

1 2 3 4 5 6 7 --> 1 2 3 4 5 7 6

And reverse all of the characters after k.

1 2 3 4 5 7 6 --> 1 2 3 4 5 7 6

In this case we only needed to do a single comparison to find k and a single comparison to find l. Reversing the elements after k was also a constant time operation because there was only a single element to reverse. This would be true whether the string was 7 characters long or if it was 100,000,000 characters long. Finding this permutation had nothing to do with the length of the string, making the best case O(1).

qfwfq
  • 2,416
  • 1
  • 17
  • 30