1

I've the following implementation for quicksort, but trying to transfer it to quickselect fails.

class Solution {
    public static void main(String[] args) {
        for (int i = 1; i < 5; i++) {
            int[] arr = new int[]{9,8,7,1,2,3,6,5,4};
            System.out.println(quicksort(arr, i));
        }
    }

    private static int quicksort(int[] arr, int k) {
        return quicksort(arr, 0, arr.length - 1, k);
    }

    private static int quicksort(int[] arr, int low, int high, int k) {
        int p = partition(arr, low, high);
        /* Doesnt work:
        if (p == k) {
            return arr[k];
        } else if (p < k) {
            return quicksort(arr, p+1, high, k);
        } else {
            return quicksort(arr, low, p-1, k);
        }
        */
    }

    private static int partition(int[] arr, int low, int high) {
        int i = low;
        int j = high;
        int pivot = arr[low + (high - low) / 2];

        while (true) {
            while (arr[i] < pivot) {
                i++;
            }
            while (arr[j] > pivot) {
                j--;
            }

            if (i < j) {
                int tmp = arr[i];
                arr[i] = arr[j];
                arr[j] = tmp;
                i++;
                j--;
            } else {
                return j;
            }
        }
    }
}

It feels like the information that everything from 0..p is smaller or equal to arr[p] and vice-versa does not help at all.

Example: 9,8,7,1,2,3,6,5,4, after partition: 2, 1, 7, 8, 9, 3, 6, 5, 4 with p = 1 (choosen pivot was 2). So I know the first and second lowest value is in 0..1 range. But it isn't sorted, so I cannot simply say if (p == k-1) return arr[p], because it isn't guaranteed that arr[p] is the max of that half, just that everything in that half is less than the choosen pivot.

Any idea how I can make it work?

Regyn
  • 585
  • 3
  • 17
  • Just looking at the Wiki page of Quickselect, I don't see how you turn one partition step into a Quickselect. It's obviously recursive. Could you make a better attempt at the code and post the result? – markspace May 01 '22 at 17:05
  • @markspace Wiki specifies that `However, when doing selection, we already know which partition our desired element lies in, since the pivot is in its final sorted position, with all those preceding it in an unsorted order and all those following it in an unsorted order. Therefore, a single recursive call locates the desired element in the correct partition, and we build upon this for quickselect`. So it should work based on the quicksort approach – Regyn May 01 '22 at 17:13
  • No, if you're trying to do it like that, then you would need to convert the recursion into a loop. In other words "a single call" is for a modified `partition` that does that loop for you. I think it's obvious. – markspace May 01 '22 at 17:29
  • `I think it's obvious`. Delightful – Regyn May 01 '22 at 17:33
  • Well, it kinda is. If you know how partition works, it's obvious that it can't return the kth element in just one call. Try working a simple example on a piece of paper, I think it will help. – markspace May 01 '22 at 17:34
  • It isn't doing one call. `private static int quicksort` is incomplete. In my sample implementation I tried ` if (p == k) { return arr[k]; } else if (p < k) { return quicksort(arr, p+1, high, k); } else { return quicksort(arr, low, p-1, k); }`, which as written didn't work due to the unsorted constraint. I've now added the code in case the text wasn't clear on what I tried and removed. Maybe the missing part wasn't visible – Regyn May 01 '22 at 17:36

0 Answers0