题解 | #第k轻的牛牛#

第k轻的牛牛

https://www.nowcoder.com/practice/7676478b46794456b145e8e48b0e2763

考察知识点:快速选择

题目分析:

题目要求在O(n)的时间复杂度下找到第k轻的牛牛,很明显应使用快速选择算法。

快速选择算法基于快速排序的思想。首先选取一个基准值,将数组中小于基准值的数放到左边,大于基准值的数放到右边。

为了不产生死循环,我们每次首先让i和j移动一位,然后再判断条件是否满足,是否可以继续移动。

最终当 i >= j 时停止,此时判断 j 和 k 的位置关系。

可以看到最终索引值比 j 小或等于 j 的数都是不大于基准值的。而范围 0 ~ i 中第i个数可能最终大于基准值。(依赖于快速选择算法的具体实现,其他实现方式可能会有所不同)。然后根据第k小的数是在范围 l ~ j 还是 j + 1 ~ r 进行递归查找。

时间复杂度:

平均情况下,每次分隔区间时,第一次遍历n个元素,第二次只需遍历n / 2个元素,第三次只需遍历n / 4个元素...那么时间复杂度是一个等比数列。设总共需要分隔x次:

n + \frac{n}{2} + \frac{n}{4} + ... + 1 = 1 * \frac{1 - 2^{x}}{1 - 2} = 2^{x} - 1

x = logn + 1,故平均情况下时间复杂度近似为O(n)

所用编程语言:C++

class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param weights int整型vector 
     * @param k int整型 
     * @return int整型
     */
    int quick_select(vector<int> &weights, int l, int r, int k) {
        if (l == r) return weights[l];
        int i = l - 1, j = r + 1, v = weights[l];
        while (i < j) {
            do i++; while (weights[i] < v);
            do j--; while (weights[j] > v);
            if (i < j) swap(weights[i], weights[j]);
        }
        if (k - 1 <= j) return quick_select(weights, l, j, k);
        else return quick_select(weights, j + 1, r, k);
    }
    int findKthSmallest(vector<int>& weights, int k) {
        // write code here
        int size = weights.size();
        int res = quick_select(weights, 0, size - 1, k);
        return res;
    }
};

全部评论

相关推荐

OPSL:钱确实给的多,但是追责这一点比较迷惑…3个月具体如何计算呢?出勤天数30*3吗?还是21*3呢?万一中间学校有安排怎么办呢?这个得多问一问呀
点赞 评论 收藏
转发
头像
点赞 评论 收藏
转发
2 收藏 评论
分享
牛客网
牛客企业服务