查找第k大的数 [中等难度算法]

第一种方法是利用快速排序。

快速排序的基本步骤是:找到轴,然后分别对左边和右边的数进行快速排序。

轴的特性是:在轴左边的数都比轴小,在轴右边的数都比轴大。

如果轴的恰好在k位置,那么轴就是第k大的数。

// 输入数组a[l..r](含边界),返回第k大的数。
int QuickSort(int arr[], int l, int r, int k) {
    if (l >= r) return arr[l];
    int i = l;
    int j = r;
    int pivot = arr[i];   // 将最左边的数选为轴
    while (i < j) {
        // j指针不断左移,直到找到arr[j]= pivot) j--;
        // 把比轴小的数挪到轴的左边
        if (i < j) {
            arr[i] = arr[j];
            i++;
        }
        // i指针不断右移,直到找到arr[i]>=pivot,即大于等于轴的数
        while (i < j && pivot > arr[i]) i++;
        // 把大于等于轴的数挪到右边
        if (i < j) {
            arr[j] = arr[i];
            j--;
        }
    }
    // 把轴的数值放到i位置
    arr[i] = pivot;
    // 如果轴的位置恰好是i,则返回轴
    if (k == i) return pivot;
    // 如果要找的位置k在轴的左边
    if (k < i)
        return QuickSort(arr, start, i - 1);
    // 如果要找的位置k在轴的右边
    else
        return QuickSort(arr, i + 1, last);
}

时间复杂度是O(n) [这边博客说的:https://blog.csdn.net/orangefly0214/article/details/86527462]

 

 

堆排序, 每次都能分一半. 堆排序是不用数据放进内存的算法。

堆排序算法的解释:https://www.cnblogs.com/ssyfj/p/9512451.html

二叉树的存储方式之一就是数组,所以数组也可以看成一棵完全二叉树。

找第k大的数,就维持一个容量为k的堆。遍历待查找数组,将每个数都放到堆里,比较小的、溢出来的就扔了。

放完一轮后,堆中最小的数就是第k大的数。

将元素插入堆的时间复杂度是O(log k),所以总时间复杂度是O(n log k)

你可能感兴趣的:(算法)