简体   繁体   中英

Kth minimum element using quickselect with random pivot

I am trying to find the kth smallest in an array using quickselect algorithm. But, when I try to select the pivot randomly, the output coming is also random.

Following is my method implementation,

    static int findKthMin(int[]arr, int n, int k) {
        int l=0 , r=n-1;
        Random random = new Random();
        while(true) {
            int x = random.nextInt(r+1-l) + l; // When using x = r (works correctly)
            int pivot = arr[x];
            int idx = l;
            for(int i=l;i<=r;i++) {
                if(arr[i] < pivot) {
                    int temp = arr[idx];
                    arr[idx] = arr[i];
                    arr[i] = temp;
                    
                    idx++;
                }
            }
            arr[x] = arr[idx];
            arr[idx] = pivot;
            
            if(idx == k-1) return pivot;
            
            if(idx > k-1) {
                r = idx-1;
            } else {
                l = idx;
            }
        }
    }

Here, n is size of array and k is the kth minimum element to be found.
The code works fine when I use x=r .

My guess is that something is wrong in the condition

   for(int i=l;i<=r;i++) {
       if(arr[i] < pivot) {
            int temp = arr[idx];
            arr[idx] = arr[i];
            arr[i] = temp;

            idx++;
       }
   }          

But I can't figure out what is wrong and how to fix it. I have spent hours debugging it and changing the code but can figure out the problem.

Here are the test cases I'm trying,

6               // n
7 10 4 3 20 15  //arr
3               // k

and,

5             // n
7 10 4 20 15  // arr
4             // k

With these test cases, random pivot is giving any of the array element as the output.
Any hint of what might be the bug will be very helpful.

After the suggestion from @Nico, I just needed to swap the pivot element with the last one.
Following is the complete working snippet,

    static int findKthMin(int[]arr, int n, int k) {
        int l=0 , r=n-1;
        Random random = new Random();
        while(true) {
            int x = random.nextInt(r+1-l) + l; // When using x = r (works correctly)

            //Swap random pivot with the last index element
            int temp = arr[x];
            arr[x] = arr[r];
            arr[r] = temp;

            int pivot = arr[r];

            int idx = l;
            for(int i=l;i<=r;i++) {
                if(arr[i] < pivot) {
                    temp = arr[idx];
                    arr[idx] = arr[i];
                    arr[i] = temp;

                    idx++;
                }
            }
            arr[r] = arr[idx];
            arr[idx] = pivot;

            if(idx == k-1) return pivot;

            if(idx > k-1) {
                r = idx-1;
            } else {
                l = idx;
            }
        }
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM