题解 | #寻找第K大-库函数-手写快排-手写快速选择算法#

寻找第K大

http://www.nowcoder.com/practice/e016ad9b7f0b45048c58a9f27ba618bf

描述

题目描述

这个题目很简单, 就是一个简单的在一个数组中寻找第kk大的元素

解法

解法一: STL库函数

实现思路

直接调用我们的STL函数, 求取第kk大的元素

代码实现

class Solution {
   public:
    int findKth(vector<int> a, int n, int K) {
        nth_element(a.begin(), a.begin() + K - 1, a.end(), greater<int>());
//         求取第k大的函数
        return a[K - 1];
    }
};

时空复杂度分析

时间复杂度: O(n)O(n)

理由如下: 这个函数只跟我们数组的大小有关系

空间复杂度: O(1)O(1)

理由如下: 我们未引入变量空间

解法二: 快速排序

实现思路

我们先把我们的数组排好序之后, 我们再进行输出第kk大的数

代码实现

class Solution {
   public:
    void quick_sort(vector<int> &q, int l, int r) {
        if (l >= r) return;
        // 递归的停止条件
        int i = l - 1, j = r + 1, x = q[l + r >> 1];
        // 分为子情况
        while (i < j) {
            do i++;
            while (q[i] > x);
            do j--;
            while (q[j] < x);
            if (i < j) swap(q[i], q[j]);
        }
        // 哨兵的移动交换
        quick_sort(q, l, j), quick_sort(q, j + 1, r);
        // 递归处理之后的问题
    }
    int findKth(vector<int> a, int n, int K) {
        quick_sort(a, 0, n - 1);
        return a[K - 1];
    }
};

时空复杂度分析

时间复杂度: O(nlogn)O(nlogn)

理由如下: 因为我们执行的快速排序, 不断递归, 平均下来我们的时间复杂度就是O(nlogn)O(nlogn)

空间复杂度: O(logn)O(logn)

理由如下: 我们要考虑调用的递归栈的深度

解法三: 快速选择算法

实现思路:

其实我们的主要思想就是一个分治, 这里就是把我们快速排序的代码给优化了一下, 首先我们是划分一个分解点, 如图所示

20220207234730

然后我们前面部分跟我们的快速排序的算法是一样的, 然后我们选定了一个xx作为我们的分界点之后, 我们就把比xx大的都放到左边, 比xx小的都放到右边, 然后我们可以得到左右区间的一个长度, 这里我们用LL表示我们左半区间的长度, RR表示我们右半区间的长度

如果我们k<=Lk <= L, 可以说明我们要找的kk是在我们的左半区间, 我们就可以只是递归我们的左半区间, 减少了右半区间的多余遍历

如果我们k>Lk > L, 我们可以知道我们要找到的kk是在我们的右半区间, 我们可以只是递归我们的右半区间, 减少了左半区间的多余遍历

代码实现

class Solution {
   public:
    int quick_sort(vector<int> &q, int l, int r, int k) {
        if (l >= r) return q[l];
        // 到达了递归的终点, 我们返回最后的结果
        int i = l - 1, j = r + 1, x = q[l + r >> 1];
        while (i < j) {
            do i++;
            while (q[i] > x);
            do j--;
            while (q[j] < x);
            if (i < j) swap(q[i], q[j]);
        }
        // 快速排序, 根据我们的x, 把我们的区间划分为两部分
        if (j - l + 1 >= k)
            return quick_sort(q, l, j, k);
        else
            return quick_sort(q, j + 1, r, k - (j - l + 1));
        // 把我们的区间长度和我们的k相比较, 看我们的k应该是在于哪一个区间, 少递归了一部分
    }

    int findKth(vector<int> a, int n, int K) {
        return quick_sort(a, 0, n - 1, K);
    }
};

时空复杂度分析

时间复杂度: 期望的时间复杂度: O(n)O(n)

理由如下: 首先我们先是不考虑我们的极端情况, 我们就是考虑一般情况, 那么我们第一次数组长度为nn, 然后我们第一次递归, 我们会遍历n2\frac{n}{2}, 然后我们递归再次划分的时候, 我们会遍历n4\frac{n}{4}, 以此类推, 最后我们把遍历的所有的相加, 我们可以知道这个数列是趋于nn的, 所以我们的时间复杂度均摊下来就是O(n)O(n)的, 但是其实快速选择算法跟快速排序算法一个很关键的问题就是他的一个基准点的选择, 这里参考算法导论的一个说明: 这个算法的最坏情况运行时间是O(n2)O(n ^ 2), 即使找最小元素也是如此, 因为我们在每次划分的时候可能极不走运的总是按余下的元素中最大的来进行划分所以我们会出现最坏的情况, 这里如果想要优化可以考虑随机化的思想, 这题不做过多赘述

空间复杂度: 期望空间复杂度:O(logn)O(logn)

理由如下: 我们这里的空间复杂度跟我们上述的时间复杂度类似,当我们一切符合期望没有极端的最差的情况出现时,我们的空间复杂度期望就是O(logn)O(logn),如果我们出现了我们上述的极端情况,那么我们递归栈的深度加深,我们的空间复杂度就会退化成为O(n)O(n)

机试题目题解 文章被收录于专栏

主要是机试题目的题目讲解和做法

全部评论

相关推荐

评论
5
1
分享

创作者周榜

更多
正在热议
更多
# 一张图晒出你司的标语 #
4440次浏览 78人参与
# 找AI工作可以去哪些公司? #
9797次浏览 290人参与
# 开放七大实习专项,百度暑期实习值得冲吗 #
15618次浏览 226人参与
# 你的实习产出是真实的还是包装的? #
20642次浏览 345人参与
# 从事AI岗需要掌握哪些技术栈? #
9605次浏览 364人参与
# 春招至今,你的战绩如何? #
67341次浏览 595人参与
# 米连集团26产品管培生项目 #
13462次浏览 285人参与
# AI面会问哪些问题? #
28823次浏览 609人参与
# 中国电信笔试 #
32210次浏览 295人参与
# 你做过最难的笔试是哪家公司 #
35309次浏览 290人参与
# 金三银四,你的春招进行到哪个阶段了? #
22501次浏览 284人参与
# 投递几十家公司,到现在0offer,大家都一样吗 #
341137次浏览 2175人参与
# 如何准备秋招 #
78321次浏览 868人参与
# 同bg的你秋招战况如何? #
212264次浏览 1121人参与
# 哪些公司真双非友好? #
69785次浏览 289人参与
# 应届生被毁约被毁意向了怎么办 #
63343次浏览 305人参与
# 阿里笔试 #
179302次浏览 1321人参与
# 机械人避雷的岗位/公司 #
62720次浏览 393人参与
# 小马智行求职进展汇总 #
25149次浏览 80人参与
# 第一份工作一定要去大厂吗 #
15089次浏览 123人参与
# 担心入职之后被发现很菜怎么办 #
291419次浏览 1210人参与
# 为了减少AI幻觉,你注入过哪些设定? #
26314次浏览 310人参与
牛客网
牛客网在线编程
牛客网题解
牛客企业服务