algorithmmedianunordered-setquick-searchmedian-of-medians

The median of an unordered set


I am a compsci student, and I received the following problem in Analysis & Design II class:

The median of an unordered set is an element such that the number of elements less than the median is within one of the number of elements that are greater, assuming no ties.

(a) Write an algorithm thst find the median of 3 distincts values a, b, c.

(b) Determine the number of comparisons your algorithm does in the average case and in the worst case.

From the little I searched and learned, it seems like this is called finding the kth element of an unsorted array, or finding the median of medians?

However, we have not learned quicksort yet, and all I could find seems way more complicated than what is asked of me here. That said, I am not entirely sure I understand the definition presented in this problem. Also, does finding the median of 3 distinct values a, b, c means finding the median of a set of size 3?

I am not necessarily looking for an answer. Just simple explanations or clarifications. Thanks.


Attempt #1

(a) Following templatetypedef's advice, I have came up with this naïve algorithm to solve this:

medianOf(int a, int b, int c)
    if a < b
        if a > c
            return a
    else //a > b
        if a < c
            return a    

    if b < c
        if b > a
            return b
    else //b > c
        if b < a
            return b

    if c < a
        if c > b
            return c
    else //c > a
        if c < b
            return c

I am aware it's very naïve and ugly, but I couldn't come up with a better solution and it already took too much of my time.

(b) It seems like the best case is when c < a < b with 2 comparisons, and the worst case is when a < c < b with 9 comparisons? So, the average would be (2+9)/2 which is 5 or 6 comparisons?

Or am I being naïve now?


Attempt #2

(a) Ok, so, following thang's advice, I tried really hard to minimize the number of comparisons to 3. Mathematically speaking, I understand your point. It is enough to check a<b, b<c, a<c and deduct the rest of the states from it, but I could not find a way to code it... This is my best attempt:

medianOf(int a, int b, int c)
    if a < b                                  1
        if c < a                              1
            return a    //c < a < b
        else  // a < b && a < c
            if b < c                          1
                return b    //a < b < c
            else
                return c    //a < c < b    

    else    //a > b
        if c > a                              1
            return a    //c > a > b
        else //a > b && a > c
            if b > c                          1
                return b    //a > b > c
            else                
                return c    //a > c > b

I don't see how I can do any better than this:

(b) Best case: 1 comparison. Average case: 5/2 = 2 to 3 comparisons. Worst case: 5 comparisons.

Any better?


Final Solution

Thanks to thang, and with a lot of effort, I finally got it. My last algorithm is correct, but my counting was wrong.

(b) Best case: 2 comparisons. Average case: 2 comparisons. Worst case: 3 comparisons.


Solution

  • Fortunately, I think you're overthinking this. :-) Think of it this way - could you implement this function?

     int medianOf(int a, int b, int c) {
          ...
     }
    

    You don't have to worry about finding the medians of arbitrary sets. Just find the median of the three inputs.

    Once you've done that, look at the comparisons you make and think about the best-case, worst-case, and average-case number of comparisons. You can directly count how many comparisons you're making because your code should be pretty short.

    The median-of-medians technique you're thinking of is for the more general case where you have an arbitrary number of elements and want to take the median of all of them. It's definitely more complex than this, but that doesn't seem to be what you're being asked to do.

    Hope this helps!