最多1G内存,找出所有出现了两次的数
思路
每个数字出现可能状态:
- 小于2次
- 等于2次
- 大于2次
使用位图,用两个bit位来进行描述可能出现的次数
40亿个非负整数,2^32位, 2 * 2^32长度的位图
2^33 bit/8bit = 2^30B = 1G
具体算法:
01:n出现了一次
10:n出现了2次
11:n出现了大于2次
对40亿个数依次进行遍历,找出状态是10的n
进阶:内存限制为10M,找中位数
中位数需要数组有序,既然不能整体解决,我们可以把数据拆分成多个等分,维持每个区间有序,先锁定第20亿和20亿零1个数所在区间,找到区间后再对区间进行精准锁定(详细统计该分区20亿个数的位置)
逆向思考
精准查找时,某个数可能出现多次,记录出现次数需要使用整数存储4B
某个小的范围多大?10M/4B = 2.5M, 不方便记录,优化为2M
分区有多少个?2^32/2M = 232/221 = 2^11 = 2048 个分区
正向解决
拆分为2048个分区,统计每个分区的数字个数 unsigned int arr[2048]
arr[n/2M]++统计这个分区的个数
找到20亿个20亿零1个数所在分区,假设找到的分区为k
声明 unsigned int arr[2^21], arr[num-k*2M]++
统计这个分区中每个数字出现的次数