[讨论贴]关于1到10 十个数据从中随机抽取一个如何高效判断那个数据被抽走

zhourenyun 2009-08-05 12:04:44
2 )上亿记的数据中如何抽取最大的50个数据(要求效率)
...全文
186 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
liao05050075 2009-08-05
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 arong1234 的回复:]
个人觉得建立一个最大长度为50的链表,不停的朝里面插入,如果插入一个元素后长度超过50,就把链表尾部删除。
这样做的好处是:
1. 空间代价最小,只需要50个存储
2. 时间效率也很高,因为我们最多进行50个元素的有序插入,用折半法最多查6次就知道插在哪儿
这个算法的时间开销是O(N)的
[/Quote]

您的这个方法有些问题。
因为链表是不能折半查找的,折半法有个随机存取的前提(可以用下标访问,比如说一个数组)
于是,这个方法就要不断地从第一个元素开始到它应该在的位置一个一个地比。

事实上,改进一下,使用小顶堆就是你这个方法的实现。

方法是:
你使用前50个元素去建立一个小顶堆,然后从第51个元素开始,每个元素先和堆顶比较,如果比堆顶大,那么就删除堆顶,把它入堆,如果比堆顶小,直接丢掉。
这个方法的空间代价也50,
时间效率是是O(n)
堆的删除和插入都是Log(50)也是折半的代价
zhourenyun 2009-08-05
  • 打赏
  • 举报
回复
果然数据高手很多,学习中。
zhhy123 2009-08-05
  • 打赏
  • 举报
回复
"2. 时间效率也很高,因为我们最多进行50个元素的有序插入,用折半法最多查6次就知道插在哪儿
这个算法的时间开销是O(N)的 "

链表不能折半查找,所以arong1234的算法是O(25N)的
上亿个数,O(n)和O(50N)是差很远的

用堆才能做到接近O(n)
arong1234 2009-08-05
  • 打赏
  • 举报
回复
由于要从1亿个中选50个,待选数目这么少,我们不需要维护一个完整得1亿个元素得排序后得树或者链表
大顶堆也许是个好得数据结构,但是用在这里不合适,原因在于:
1. 它应该假定存在一个已经排序好得堆,而这是不存在得
2. 我们得挑选应该是一次性得,而为了这个一次性得挑选建立一个复杂得堆也不值得

个人觉得建立一个最大长度为50的链表,不停的朝里面插入,如果插入一个元素后长度超过50,就把链表尾部删除。
这样做的好处是:
1. 空间代价最小,只需要50个存储
2. 时间效率也很高,因为我们最多进行50个元素的有序插入,用折半法最多查6次就知道插在哪儿
这个算法的时间开销是O(N)的
[Quote=引用 4 楼 zhourenyun 的回复:]
引用 2 楼 lzy0001sl 的回复:
我看大顶堆是个办法

大顶堆的解释
我自己数据结构没学好,所以把解释也发上来 :)
堆顶元素是最大的,它的叶子都比它小,以叶子为根,也作同样的规则
从n/2开始向上筛选,如本例中,即从第4个97开始筛选
                            49
                      /          \
                    38          65
                  /      \        /      \
              97    76    13    27
              /
          49
97的子树均比根小,所以满足大顶堆的定义,向上65也满足,38不满足,因此将38为根的子树调整为大顶堆为:
                            49
                      /          \
                    97          65
                  /      \        /      \
              49    76    13    27
              /
          38
再向上,以49为根的树不满足大顶堆的定义,调整为
                            97
                      /          \
                    76          65
                  /      \        /      \
              49    49    13    27
              /
          38
完毕

[/Quote]
  • 打赏
  • 举报
回复
第一题,用3楼方法不错
第二题,同意2楼,用堆排序比较好。
zhourenyun 2009-08-05
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 arong1234 的回复:]
问题1:对余下得数求和,55-得到得和就是少得数
问题2:插入排序,并且在插入时如果队列长度大于50,就抛弃队列尾巴

[/Quote]
1 仅仅用加法和减法 效率确实好 我也想过1+10 2+9 但是却没有想到相减 厉害
zhourenyun 2009-08-05
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 lzy0001sl 的回复:]
我看大顶堆是个办法
[/Quote]
大顶堆的解释
我自己数据结构没学好,所以把解释也发上来 :)
堆顶元素是最大的,它的叶子都比它小,以叶子为根,也作同样的规则
从n/2开始向上筛选,如本例中,即从第4个97开始筛选
49
/ \
38 65
/ \ / \
97 76 13 27
/
49
97的子树均比根小,所以满足大顶堆的定义,向上65也满足,38不满足,因此将38为根的子树调整为大顶堆为:
49
/ \
97 65
/ \ / \
49 76 13 27
/
38
再向上,以49为根的树不满足大顶堆的定义,调整为
97
/ \
76 65
/ \ / \
49 49 13 27
/
38
完毕
arong1234 2009-08-05
  • 打赏
  • 举报
回复
问题1:对余下得数求和,55-得到得和就是少得数
问题2:插入排序,并且在插入时如果队列长度大于50,就抛弃队列尾巴
lzy0001sl 2009-08-05
  • 打赏
  • 举报
回复
我看大顶堆是个办法
zhourenyun 2009-08-05
  • 打赏
  • 举报
回复
问题1 我的答案是
用数组A[10]
如果遇到 6 a[5] = 0
然后取出数组中为1 的数据就OK了 可能效率不好,有没有高手指点下。
问题二
没有什么好的思路。
用排序 可能不太好
用数据库 可能也不太好,所以....

敬请各位指点。
xc00737 2009-08-05
  • 打赏
  • 举报
回复
仰望3楼 学习了

33,311

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 新手乐园
社区管理员
  • 新手乐园社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧