1

Here is the code for quickselect

def quickSelect(lst, k):
if len(lst) != 0:
    pivot = lst[(len(lst)) // 2]
    smallerList = []
    for i in lst:
        if i < pivot:
            smallerList.append(i)
    largerList = []
    for i in lst:
        if i > pivot:
            largerList.append(i)
    count = len(lst) - len(smallerList) - len(largerList)
    m = len(smallerList)
    if k >= m and k < m + count:
        return pivot
        print(pivot)
    elif m > k:
        return quickSelect(smallerList, k)
    else:
        return quickSelect(largerList, k-m-count)

the issue I am having with it is that it runs with no errors or anything, but when it completes itself I am expecting it to output something to the python shell (in this specific case a median of a list), but I get nothing back. Am I doing something wrong here?

As for what I am inputting for lst and k....

  • lst = [70, 120, 170, 200]
  • k = len(lst) // 2

I have tried it with a few different k values as well but to no avail

BLU
  • 121
  • 1
  • 2
  • 7
  • Might be just poor formatting, but your indentation is wrong. You're not indenting after the function definition. – Øyvind Robertsen Oct 07 '13 at 22:29
  • I just ran it (fixing the indenting) and with your input for lst and k and quickSelect(lst, k) returned 170. Could you say how you're calling quickSelect and what your expecting? Try print(quickSelect(lst, k))) to be sure the interpreter prints the result. – Greg Whittier Oct 07 '13 at 22:36

2 Answers2

3

You can optimize this algorithm using list comprehension. Also, I don't think you need count...

 def quickSelect(seq, k):
    # this part is the same as quick sort
    len_seq = len(seq)
    if len_seq < 2: return seq

    ipivot = len_seq // 2
    pivot = seq[ipivot]

    smallerList = [x for i,x in enumerate(seq) if x <= pivot and  i != ipivot]
    largerList = [x for i,x in enumerate(seq) if x > pivot and  i != ipivot]

    # here starts the different part
    m = len(smallerList)
    if k == m:
        return pivot
    elif k < m:
        return quickSelect(smallerList, k)
    else:
        return quickSelect(largerList, k-m-1)




if __name__ == '__main__':
    # Checking the Answer
    seq = [10, 60, 100, 50, 60, 75, 31, 50, 30, 20, 120, 170, 200]

    # we want the middle element
    k = len(seq) // 2

    # Note that this only work for odd arrays, since median in
    # even arrays is the mean of the two middle elements
    print(quickSelect(seq, k))
    import numpy
    print numpy.median(seq)
bt3gl
  • 31
  • 4
  • Your code is excellent, but it would be even simpler if `pivot` was simply defined as `seq[0]`; that way you would not need to use `enumerate` at all: `smallerList = [x for x in in seq[1:] if x <= pivot]` and `largerList = [x for x in seq[1:] if x > pivot]`. – cjauvin Sep 01 '14 at 01:38
  • We could this, however we need to be careful with the pivot's choice. For instance, if we end up always parting into n-1 subarrays, quicksort will have a runtime O(n^2) instead of O(nlogn). Choosing the pivot in the middle doesn't prevent this to happen, but it makes it less likely than choosing the pivot in the beginning. – bt3gl Sep 01 '14 at 03:35
0
def quickSelect(lst, k):
    if len(lst) != 0:
        pivot = lst[(len(lst)) // 2]
        smallerList = []
        for i in lst:
            if i < pivot:
                smallerList.append(i)
        largerList = []
        for i in lst:
            if i > pivot:
                largerList.append(i)
        count = len(lst) - len(smallerList) - len(largerList)
        m = len(smallerList)
        if k >= m and k < m + count:
            return pivot
            print(pivot)
        elif m > k:
            return quickSelect(smallerList, k)
        else:
            return quickSelect(largerList, k-m-count)

lst = [70, 120, 170, 200]
k = len(lst) // 2

print(quickSelect(lst, k))

produces

>>> 170

The only thing I corrected was the indenting.

Greg Whittier
  • 3,105
  • 1
  • 19
  • 14
  • the "print(quickSelect(lst, k))" was my issue. I was calling for print within the function. When I ran it like this it worked. Formatting was actually correct I just copy+pasted it weird into here. Thanks :) – BLU Oct 08 '13 at 19:55