比特数据结构与算法(第四章_中_续②)堆解决Topk问题(最小的k个数)

news/2024/5/20 9:18:06 标签: c语言, 数据结构, 算法, leetcode,

TopK问题介绍:

在N个数中找出最大/小的前K个 (比如在1000个数中找出最大/小的前10个)

以前的方法:冒泡排序。时间复杂度: O(N^2)

现在找最大的k个数的方法:

方法1:排序降序,前N个就是最大的。上篇学过时间复杂度: O(N*logN)

方法2:N个数依次插入大,HeapPop K次,每次取顶的数据,即为前K

时间复杂度: O(K*logN)

假设 N非常大, 是 10 亿,内存中存不下这些数,它们存在文件中的。 K是 100,
上面的方法就都不能用了……
话说 10 亿个整数,大概占用多少空间?
1G = 1024MB
1G = 1024*1024KB
1G = 1024*1024*1024Byte
要占用10亿字节!所以我们来看看方法3:

方法3:

这里为什么使用小而不使用大

最大的前K个数一定会比其他数要大,只要进来的数比顶数据大,就替代它。

因为是小(小的在上大的在下),最大的数进去后一定会沉到下面,

所以不可能存在大的数堵在顶导致某个数进不去的情况,数越大沉得越深。

对应地,如果使用大就会出现一个大数堵在顶,剩下的数都比这个大数小,

导致其他数进不来,最后只能选出最大的那一个。

剑指 Offer 40. 最小的k个数

难度简单

输入整数数组 arr ,找出其中最小的 k 个数。例如,输入4、5、1、6、2、7、3、8这8个数字,

则最小的4个数字是1、2、3、4。

示例 1:

输入:arr = [3,2,1], k = 2

输出:[1,2] 或者 [2,1]

示例 2:

输入:arr = [0,1,2,1], k = 1

输出:[0]

限制:

  • 0 <= k <= arr.length <= 10000

  • 0 <= arr[i] <= 10000

/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
int* getLeastNumbers(int* arr, int arrSize, int k, int* returnSize){

}

解析代码:

/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
void justDown(int* arr, int n, int root)//大下调
{
    int father = root;
    int child = father * 2 + 1;//默认左孩子大
    while (child < n)
    {
        if (child + 1 < n && arr[child] < arr[child + 1])
        {  // 如果右孩子存在且右孩子比左孩子大
            child++;
        }
        if (arr[father] < arr[child])
        {
            int tmp = arr[father];
            arr[father] = arr[child];
            arr[child] = tmp;

            father = child;
            child = father * 2 + 1;
        }
        else
        {
            break;
        }
    }
}
int* getLeastNumbers(int* arr, int arrSize, int k, int* returnSize) {
    *returnSize = k;
    if (k == 0)//回头处理k==0
    {
        return NULL;
    }
    int* retArr = (int*)malloc(sizeof(int) * k);
    for (int i = 0;i < k;i++)
    {
        retArr[i] = arr[i];
    }
    for (int i = (k - 1 - 1) / 2;i >= 0;i--) //建的for写法
    {
        justDown(retArr, k, i);
    }
    for (int j = k;j < arrSize;j++)
    {
        if (arr[j] < retArr[0])
        {
            retArr[0] = arr[j];
            justDown(retArr, k, 0);
        }
    }
    //*returnSize = k; 写到这发现有个测试用例跑不了,到上面处理一下
    return retArr;
}


http://www.niftyadmin.cn/n/105103.html

相关文章

高级前端面试题汇总

iframe 有那些优点和缺点&#xff1f; iframe 元素会创建包含另外一个文档的内联框架&#xff08;即行内框架&#xff09;。 优点&#xff1a; 用来加载速度较慢的内容&#xff08;如广告&#xff09;可以使脚本可以并行下载可以实现跨子域通信 缺点&#xff1a; iframe 会…

我的Android前沿技术—— Artifactory私服 搭建

我们说的私服&#xff0c;其实指的是企业局域网内的软件包依赖库。 说到软件库&#xff0c;就会牵扯出另一个概念——包管理器。 包管理器是在电脑中自动安装、配置、卸载和升级软件包的工具组合。包管理器由于其便捷性&#xff0c;被越来越多的新技术所采纳&#xff0c;从老…

漫谈丨集团企业的电子档案怎么管?

今天聊聊集团企业电子档案建设的话题&#xff0c;根据这么多年的项目实践经验&#xff0c;可以从以下4个角度解决。 一般情况下&#xff0c;集团企业档案电子化是由集团本部顶层设计&#xff0c;下属产业集团企业试点执行&#xff0c;数据需要隔离&#xff0c;独立应用。 集团…

2023-2-27 刷题情况

求出最多标记下标 题目描述 给你一个下标从 0 开始的整数数组 nums 。 一开始&#xff0c;所有下标都没有被标记。你可以执行以下操作任意次&#xff1a; 选择两个 互不相同且未标记 的下标 i 和 j &#xff0c;满足 2 * nums[i] < nums[j] &#xff0c;标记下标 i 和 j…

图解鼠标事件的 ScreenX ,LayerX,clientX,PageX,offsetX,X

前言&#xff1a; 完在上一篇文章 &#x1f381;如何实现原生 JS 的拖拽效果我中使用到了 MouseEvent 事件对象身上的 clienX 的属性&#xff0c;但同时我也注意到了事件对象身上关于 X 的相关属性还有很多&#xff0c;并且在移动端开发中&#xff0c;这些属性需要频繁的用到&a…

计算机网络-- 分类、体系结构(day03)

计算机网络的分类 计算机网络的性能指标 速率 数据块&#xff08;文件&#xff09;的大小单位是以2^10(1024)为一个级别递增。 例如&#xff1a; 1MB大小的文件&#xff0c;在网速为1Mbps发送的时间需要多少 文件大小的M是2进制来表示的&#xff0c;网速的M为10进制来表示的 …

尚医通(二十五)就医提醒和预约统计

目录一、就医提醒1、搭建定时任务模块二、后台管理系统-预约统计功能1、开发每天预约数据接口2、封装远程调用接口3、搭建统计分析模块4、整合统计功能前端一、就医提醒 我们通过定时任务&#xff0c;每天8点执行&#xff0c;提醒就诊 1、搭建定时任务模块 &#xff08;1&…

re.sub()用法的详细介绍

一、前言 在字符串数据处理的过程中&#xff0c;正则表达式是我们经常使用到的&#xff0c;python中使用的则是re模块。下面会通过实际案例介绍 re.sub() 的详细用法&#xff0c;该函数主要用于替换字符串中的匹配项。 二、函数原型 首先从源代码来看一下该函数原型&#xf…