package NC;
/**
 * NC88 寻找第K大
 * 有一个整数数组,请你根据快速排序的思路,找出数组中第 k 大的数。
 *
 * 给定一个整数数组 a ,同时给定它的大小n和要找的 k ,请返回第 k 大的数(包括重复的元素,不用去重),保证答案存在。
 * 要求:时间复杂度 O(nlogn),空间复杂度 O(1)
 *
 * @author Tang
 * @date 2021/10/11
 */
public class FindKth {
    /**
     * 写个快排
     * 快排原理—每一组交换为了找到数组最中间的数字
     *
     * @param a
     * @param n
     * @param K
     * @return
     */
    public int findKth(int[] a, int n, int K) {
        // write code here
        quickSort(a, 0, n-1);
        return a[n - K];
    }
    /**
     * 写个快排
     *  快排原理: 将数组第一个值当作base,给base找到数组中该有的位置
     *  比base小的都放在左边,比base大的都放在右边
     * @param a
     * @param start
     * @param end
     */
    private void quickSort(int[] a, int start, int end) {
        if(start >= end) {
            return;
        }
        int i = start;
        int j = end;
        //给base找到合适位置
        int base = a[start];
        while(i < j) {
            while (i < j && base <= a[j]) {
                j--;
            }
            if(i < j && base > a[j]) {
                int temp = a[i];
                a[i] = a[j];
                a[j] = temp;
                i++;
            }
            while (i < j && base >= a[i]) {
                i++;
            }
            while (i < j && base < a[i]) {
                int temp = a[i];
                a[i] = a[j];
                a[j] = temp;
                j--;
            }
        }
        a[i] = base;
        quickSort(a, start, i-1);
        quickSort(a, i+1, end);
    }
    public static void main(String[] args) {
        int[] num = {10,10,9,9,8,7,5,6,4,3,4,2};
        int kth = new FindKth().findKth(num, 12, 3);
        System.out.println(kth);
    }
}