面试题:如何 O(n) 的复杂度内筛选 60 亿人的身高

2023-05-29 16:08:00 +08:00
 Daredevil0086

完整的题目差不多是这样的:

现在有一个文件 a.txt ,其中放的内容就是 60 亿人的身高,每个身高数据都保证是以.0 或者.5 结尾的(比如说 180.0 ,175.5 );现在请筛选出其中前 1000 高的数据;

要求时间复杂度是 o(n);

面试官说这玩意不是一个单纯的算法,身高数据可以做点文章……但到最后还是没想出来………………有没有高智商 V 友可以解答一下

10031 次点击
所在节点    程序员
87 条回复
UnknoownUser
2023-05-29 16:32:39 +08:00
// (3-1.9)/0.05=22
int counter[22];
UnknoownUser
2023-05-29 16:35:30 +08:00
@UnknoownUser 时间复杂度为 O(n)就只能每个数据都访问一次咯,大致猜测一下前 1000 高的人类应该在 1.9-3.0m 之间,所以遍历一次用计数器把它们都记录下来
xuanbg
2023-05-29 16:38:08 +08:00
6 楼正解
FACEB00K
2023-05-29 16:38:26 +08:00
@codingbody
@picone k 不是一个常数吗,这里是 1000
tuxz
2023-05-29 16:40:04 +08:00
线性直方图
icyalala
2023-05-29 16:45:11 +08:00
"前 1000 高的数据" 要去重吗?
picone
2023-05-29 16:45:57 +08:00
@FACEB00K #24 其实是 n 次 大小为 1000 的堆插入,应该是 n * log2(1000)
lymanlai
2023-05-29 16:48:31 +08:00
感觉在写回字的几种写法。。
mxT52CRuqR6o5
2023-05-29 16:49:04 +08:00
我很怀疑面试官是不是自以为是的认为桶排序算是一种优化
IwfWcf
2023-05-29 16:52:33 +08:00
面试官都提示得那么明显了,就是在提示桶的数量很少啊……
FACEB00K
2023-05-29 16:57:39 +08:00
@picone 一般是像你这么算的,每次都是和堆顶比较,比堆顶大的才删除堆顶,再插入;如果比堆顶小,直接就 pass 了,算法复杂度就是 O(nlogk);但是身高应该是符合正态分布的,前 1000 名身高可能只占百分之零点零几,甚至更少,60 亿数据中,基本上没多少次插入
tyler1128
2023-05-29 17:00:09 +08:00
受 6 楼启发,480 个桶,先取 1000 个放入各自的桶内,然后淘汰掉数量不为 0 的最小的桶后面的所有桶,初始化一个计数器,初始值为最小的桶内令牌的数量。后面再次取数时,如果小于最小的桶,直接丢弃(节省哈希时间),如果这个数是此时场上最小的桶,则计数器加 1 ,如果不是最小的桶,计数器-1 ,当计数器为 0 时,丢弃最小的桶,重新排序找到新的最小的桶,计数器设置为新的最小的桶内令牌数量。重复该操作,直到遍历完 60 亿数,此时剩下的就是最大的 1000 个(数量可能会超过 1000 ,因为最小的桶可能有很多相同的值)。
picone
2023-05-29 17:00:14 +08:00
@FACEB00K #31 题目没有这个假设,这样不太合适。 即使有这个假设,按照二八分布,顶多也只能是 0.8n + 0.2 * n * log2(1000),也不完全是 O(n)
HashV2
2023-05-29 17:00:36 +08:00
嗯 应该就是先考察一个 topk 的算法问题,然后主要让你谈这个数据可以干嘛

60 亿是一个全球人数级别的数据,但是我也想不出这个数据到底可以做啥文章😂
UIXX
2023-05-29 17:01:50 +08:00
也不考虑 O(n),我们的期望是 [一轮遍历+尽可能少的空间] 达到筛选目的。

在现实中处理此类问题需要数据清洗并建模,简单地,我们需要预估身高分布,比如是全随机分布还是正态分布?

无论是哪一种,我们都能估算出一个合适的身高范围,如果用桶,这个范围会使桶的数量大大减少。
wanguorui123
2023-05-29 17:08:56 +08:00
分别创建:List ,最大变量 A ,最小变量 B ,遍历 txt 数据时每次和最大变量 A 和最小变量 B 对比,将最大数据计入即可,然后加入 List ,让 List 始终保持 1000 个以内即可,遍历完成后对 List 快速排序既可以,非常简答
akira
2023-05-29 17:15:34 +08:00
这样 身高数据 是有限的啊。。统计出 每个高度的人数,然后从上往下拿够 1000 个
pkoukk
2023-05-29 17:16:20 +08:00
@wanguorui123
不行的。假如数据集中的第一个值是 max,第二个值是 min ,那 list 跑到最后只有两个元素。
e7
2023-05-29 17:33:50 +08:00
1L 就已经给出标准答案了,任何带比较的都超过 O(n)了,btw:面试官挺无聊的
mmuggle
2023-05-29 17:59:07 +08:00
2000cm 不够高是吧?直接 O(1) 🤣

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/943925

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX