无序数组找中位数_无序数组的中位数-程序员宅基地

技术标签: 算法题  基础知识  

1.无序数组找中位数

  1. 思路一
    把无序数组排好序,取出中间的元素
    时间复杂度 采用普通的比较排序法 O(N*logN)
    如果采用非比较的计数排序等方法, 时间复杂度 O(N), 空间复杂度也是O(N).

  2. 思路二
    (1)将前(n+1)/2个元素调整为一个小顶堆
    (2)对后续的每一个元素,和堆顶比较,如果小于等于堆顶,丢弃之,取下一个元素。 如果大于堆顶,用该元素取代堆顶,调整堆,取下一元素。重复2.2步
    (3)当遍历完所有元素之后,堆顶即是中位数。
    注:如果数组元素的个数是奇数,取数组前(size+1)/2个元素建堆,如果是偶数则取前 size/2 个元素建堆。但如果是数据流,数据个数是动态变动的,则应采用小根堆+大根堆的办法,具体见本文第5点介绍。

  3. 思路三
    找中位数也可以用快排分治的思想。具体如下:
    (1)任意挑一个元素,以改元素为支点,划分集合为两部分,如果左侧集合长度恰为 (n-1)/2,那么支点恰为中位数。如果左侧长度<(n-1)/2, 那么中位点在右侧,反之,中位数在左侧。
    (2)进入相应的一侧继续寻找中位点。
    注:可参考快排思想实现Top K

拓展:查找N个元素中的第K个小的元素,假设内存受限,仅能容下K/4个元素
分趟查找:

  1. 第一趟,用堆方法查找最小的K/4个小的元素,同时记录剩下的N-K/4个元素到外部文件。
  2. 第二趟,用堆方法从第一趟筛选出的N-K/4个元素中查找K/4个小的元素,同时记录剩下的N-K/2个元素到外部文件。
  3. 第四趟,用堆方法从第一趟筛选出的N-K/3个元素中查找K/4个小的元素,这是的第K/4小的元素即使所求。

https://blog.csdn.net/zdl1016/article/details/4676882


2.将十进制数字转化为X 进制的字符串

//将十进制数转化为X进制字符串 
string trans(int num, int base){
    
	string str;
	while(num > 0){
    
		if(num % base < 10)
			str += num % base + '0';
		else
			str += num % base - 10 + 'A';
		num = num / base;
	}
	reverse(str.begin(),str.end());
	
	return str;
}

3.找出字符串中第k次出现的字符

  1. 思路一
    遍历这个字符串(缺点是要对这个字符串查找好多次)
  2. 思路二
    (1) 先创建一个数组然后这个数组你就放成256个元素。
    (2) 把这个字符串转化成ASCLL码进行查找。(因为ASCLL码的范围比较小)
    (3) 当我们发现字符串中出现a(a的ASCLL为97)的时候,我们可以把刚才256个元素中下边为97的元素的值加一。
char find_first_K(string str, int K)
{
    
	int count[256] = {
     0 };
	for (char ch : str) ++count[ch];

	for (char ch : str) {
    
		if (count[ch] == K)
			return ch;
	}

	return '0';
}

5.找出数据流中的中位数

在这里插入图片描述

注意:始终保证小根堆A中元素个数不少于大根堆B中的元素个数,即A、B元素相等时,将B中最大元素加入A,否则将A中最小元素加入B,来维持元素个数平衡。

class MedianFinder {
    
private:
    priority_queue<int,vector<int>, greater<int>> A;    //小根堆
    priority_queue<int,vector<int>, less<int>> B;       //大根堆

public:
    //插入新元素
    void addNum(int num) {
    
        if(A.size()==B.size()){
     //把B中最大元素加入到A
            B.push(num);
            A.push(B.top());
            B.pop();
        }else{
                      //把A中最小元素加入到B
            A.push(num);
            B.push(A.top());
            A.pop();
        }
    }
    
    //查找当前中位数
    int findMedian() {
    
        return A.size()==B.size()?(A.top()+B.top())/2.0:A.top();
    }
};

6.英文字符串流和中文字符串流如何分词

一种对英文字符串进行分词的方法:https://d.wanfangdata.com.cn/periodical/jsjyyyj200707016

字典与统计相结合的中文分词方法:https://d.wanfangdata.com.cn/periodical/xxwxjsjxt200609039

暴力方法:

  1. 英文分词:根据字符串中的空格、标点符号进行分词。
  2. 中文分词:固定两个字为一词进行拆分。

7.10亿QQ号去重

1. 内存够的情况

分段、map、多线程。

  1. 分段:哈希分桶,根据哈希值对桶数目取模得到对应桶号。
  2. map:需要计数采用unordered_map去重;不需要计数采用set去重。
  3. 多线程:将数据进行哈希分桶之后,各桶内map的去重可以采用多线程执行。

2. 内存不够的情况

思路一:bitmap

位图bitmap:每个int数字只用一个比特位来做标记

位图的操作(算法)基本依赖于下面3个元操作:

set_bit(char x, int n); //将x的第n位置1,可以通过x |= (1 << n)来实现

clr_bit(char x, int n); //将x的第n位清0,可以通过x &= ~(1 << n)来实现

get_bit(char x, int n); //取出x的第n位的值,可以通过(x >> n) & 1来实现

比如,要对数字int x = 1848105做标记,就可以调用set_bit(bit_map[x/8], x%8);

除法看做求“组编号”,x/8即是 以8个位为一个小组,分组到编号为idx = x/8的bit_map元素中,然后在组内偏移lft = x%8个比特位。

10亿数字(int 32位):10^8 * 32 / 8 = 40亿字节 / 1024 ≈ 400万 KB / 1024 ≈ 4000 MB / 1024 ≈ 4 GB
int 32位所需bitmap大小:2^32 / 8 = 2^29 字节 / 1024 = 2^19 KB / 1024 = 2^9 MB = 512 MB

10亿数字(long long 64位):4 GB * 2 = 8GB
long long 64位所需bitmap大小:2^64 / 2^23 = 2^41 MB / 1024 = 2^31 GB / 1024 = 2^21 TB / 1024 = 2048 PB = 2 EB

https://www.cnblogs.com/zhanghaiba/p/3594559.html

思路二:多路归并排序

问题:如何给100亿个数字排序?

注:100亿个 int 型数字放在文件里面大概有 37.2GB

  1. 把这个37GB的大文件,用哈希分成1000个小文件,每个小文件平均38MB左右(理想情况),把100亿个数字对1000取模,模出来的结果在0到999之间,每个结果对应一个文件,所以我这里取的哈希函数是 h = x % 1000,哈希函数取得”好”,能使冲突减小,结果分布均匀。
  2. 按各输入文件中下一个读到的元素的大小构造一个输入流最小堆.
  3. 从堆顶文件里读一个元素并写入输出文件.
  4. 同时按读的那个文件的下一个元素的值调整堆.
  5. 若第3步已到达文件结尾.则从堆中删除该输入流.
  6. 如果堆中还有元素. 回到第2步.

3. 外存不够的情况

考虑是不是可以进行分布式处理

待查~


版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_43202635/article/details/115425414

智能推荐

攻防世界_难度8_happy_puzzle_攻防世界困难模式攻略图文-程序员宅基地

文章浏览阅读645次。这个肯定是末尾的IDAT了,因为IDAT必须要满了才会开始一下个IDAT,这个明显就是末尾的IDAT了。,对应下面的create_head()代码。,对应下面的create_tail()代码。不要考虑爆破,我已经试了一下,太多情况了。题目来源:UNCTF。_攻防世界困难模式攻略图文

达梦数据库的导出(备份)、导入_达梦数据库导入导出-程序员宅基地

文章浏览阅读2.9k次,点赞3次,收藏10次。偶尔会用到,记录、分享。1. 数据库导出1.1 切换到dmdba用户su - dmdba1.2 进入达梦数据库安装路径的bin目录,执行导库操作  导出语句:./dexp cwy_init/[email protected]:5236 file=cwy_init.dmp log=cwy_init_exp.log 注释:   cwy_init/init_123..._达梦数据库导入导出

js引入kindeditor富文本编辑器的使用_kindeditor.js-程序员宅基地

文章浏览阅读1.9k次。1. 在官网上下载KindEditor文件,可以删掉不需要要到的jsp,asp,asp.net和php文件夹。接着把文件夹放到项目文件目录下。2. 修改html文件,在页面引入js文件:<script type="text/javascript" src="./kindeditor/kindeditor-all.js"></script><script type="text/javascript" src="./kindeditor/lang/zh-CN.js"_kindeditor.js

STM32学习过程记录11——基于STM32G431CBU6硬件SPI+DMA的高效WS2812B控制方法-程序员宅基地

文章浏览阅读2.3k次,点赞6次,收藏14次。SPI的详情简介不必赘述。假设我们通过SPI发送0xAA,我们的数据线就会变为10101010,通过修改不同的内容,即可修改SPI中0和1的持续时间。比如0xF0即为前半周期为高电平,后半周期为低电平的状态。在SPI的通信模式中,CPHA配置会影响该实验,下图展示了不同采样位置的SPI时序图[1]。CPOL = 0,CPHA = 1:CLK空闲状态 = 低电平,数据在下降沿采样,并在上升沿移出CPOL = 0,CPHA = 0:CLK空闲状态 = 低电平,数据在上升沿采样,并在下降沿移出。_stm32g431cbu6

计算机网络-数据链路层_接收方收到链路层数据后,使用crc检验后,余数为0,说明链路层的传输时可靠传输-程序员宅基地

文章浏览阅读1.2k次,点赞2次,收藏8次。数据链路层习题自测问题1.数据链路(即逻辑链路)与链路(即物理链路)有何区别?“电路接通了”与”数据链路接通了”的区别何在?2.数据链路层中的链路控制包括哪些功能?试讨论数据链路层做成可靠的链路层有哪些优点和缺点。3.网络适配器的作用是什么?网络适配器工作在哪一层?4.数据链路层的三个基本问题(帧定界、透明传输和差错检测)为什么都必须加以解决?5.如果在数据链路层不进行帧定界,会发生什么问题?6.PPP协议的主要特点是什么?为什么PPP不使用帧的编号?PPP适用于什么情况?为什么PPP协议不_接收方收到链路层数据后,使用crc检验后,余数为0,说明链路层的传输时可靠传输

软件测试工程师移民加拿大_无证移民,未受过软件工程师的教育(第1部分)-程序员宅基地

文章浏览阅读587次。软件测试工程师移民加拿大 无证移民,未受过软件工程师的教育(第1部分) (Undocumented Immigrant With No Education to Software Engineer(Part 1))Before I start, I want you to please bear with me on the way I write, I have very little gen...

随便推点

Thinkpad X250 secure boot failed 启动失败问题解决_安装完系统提示secureboot failure-程序员宅基地

文章浏览阅读304次。Thinkpad X250笔记本电脑,装的是FreeBSD,进入BIOS修改虚拟化配置(其后可能是误设置了安全开机),保存退出后系统无法启动,显示:secure boot failed ,把自己惊出一身冷汗,因为这台笔记本刚好还没开始做备份.....根据错误提示,到bios里面去找相关配置,在Security里面找到了Secure Boot选项,发现果然被设置为Enabled,将其修改为Disabled ,再开机,终于正常启动了。_安装完系统提示secureboot failure

C++如何做字符串分割(5种方法)_c++ 字符串分割-程序员宅基地

文章浏览阅读10w+次,点赞93次,收藏352次。1、用strtok函数进行字符串分割原型: char *strtok(char *str, const char *delim);功能:分解字符串为一组字符串。参数说明:str为要分解的字符串,delim为分隔符字符串。返回值:从str开头开始的一个个被分割的串。当没有被分割的串时则返回NULL。其它:strtok函数线程不安全,可以使用strtok_r替代。示例://借助strtok实现split#include <string.h>#include <stdio.h&_c++ 字符串分割

2013第四届蓝桥杯 C/C++本科A组 真题答案解析_2013年第四届c a组蓝桥杯省赛真题解答-程序员宅基地

文章浏览阅读2.3k次。1 .高斯日记 大数学家高斯有个好习惯:无论如何都要记日记。他的日记有个与众不同的地方,他从不注明年月日,而是用一个整数代替,比如:4210后来人们知道,那个整数就是日期,它表示那一天是高斯出生后的第几天。这或许也是个好习惯,它时时刻刻提醒着主人:日子又过去一天,还有多少时光可以用于浪费呢?高斯出生于:1777年4月30日。在高斯发现的一个重要定理的日记_2013年第四届c a组蓝桥杯省赛真题解答

基于供需算法优化的核极限学习机(KELM)分类算法-程序员宅基地

文章浏览阅读851次,点赞17次,收藏22次。摘要:本文利用供需算法对核极限学习机(KELM)进行优化,并用于分类。

metasploitable2渗透测试_metasploitable2怎么进入-程序员宅基地

文章浏览阅读1.1k次。一、系统弱密码登录1、在kali上执行命令行telnet 192.168.26.1292、Login和password都输入msfadmin3、登录成功,进入系统4、测试如下:二、MySQL弱密码登录:1、在kali上执行mysql –h 192.168.26.129 –u root2、登录成功,进入MySQL系统3、测试效果:三、PostgreSQL弱密码登录1、在Kali上执行psql -h 192.168.26.129 –U post..._metasploitable2怎么进入

Python学习之路:从入门到精通的指南_python人工智能开发从入门到精通pdf-程序员宅基地

文章浏览阅读257次。本文将为初学者提供Python学习的详细指南,从Python的历史、基础语法和数据类型到面向对象编程、模块和库的使用。通过本文,您将能够掌握Python编程的核心概念,为今后的编程学习和实践打下坚实基础。_python人工智能开发从入门到精通pdf

推荐文章

热门文章

相关标签