锁定老帖子 主题:一道腾讯面试题
精华帖 (0) :: 良好帖 (0) :: 新手帖 (1) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2010-08-31
抛出异常的爱 写道 随机找到个数
把数据重排一下 大于这数的放左 小于这数的放右 少的部分变成一个箱的总个数其它不管 多的那边再生成两个箱 每次计算出来中值可能在哪个箱中 就拆哪个箱子 左右摆动直到中间的数组足够小。。。。 这个复杂度是 O(n*lgn) 简单来说,你至少需要一个10G的箱。 时间复杂度是一说,空间复杂度如何? |
|
返回顶楼 | |
发表时间:2010-08-31
HeDYn 写道 1、遍历一遍数据,找出最大值和最小值。
2、(最大值+最小值)/2 得中间值。 3、再遍历一遍数据,找出与中间值差值最小的数。 就拿5个值的情况来看, 1, 2, 3, 4, 100 按你的算法出来的结果是4,其目标结果是3 |
|
返回顶楼 | |
发表时间:2010-08-31
swen00 写道 zwhc 写道 从海量数据中找出中位数
http://blog.chinaunix.net/u3/94271/showart_2020121.html 这个思路差不多,定义多个连续整形范围的文件 整数范围是0 - 2^32 - 1,一共有4G种取值,映射到256M个区段 然后将文件一部分一部分的读,放入区段文件中... 这个算法应该是最优的。 设映射空间为x,则第m个映射空间的映射大小是(MAXINT / x) * (m, m + 1) 第一次读入文件,但不记录数据,只记录数据在某个映射空间的数量, 经过第一次编历后,可以获得每个区间的统计数, 然后计算,获得中位数的区间。这是一次O(n)的处理。内存空间为常量 第二次处理,设置一个长度为x的投射空间,再一次读入文件, 把数据投入这个空间,同时做累计处理。第二次获得的精细值结合前面一次 的前后位置统计值进行校准,从而获得中位数。第二次处理也是O(n)的运算,内存同样是常量。 所以这是一个O(n)的运算,内存复杂度为常量。至少,题目得解。 一个tricky的东西是,在算法导论中有一个著名算法,求中位数。但难度比这个大很多, 原因是这个题目知道样本空间为有限的整数空间,所以直接投影可以解决所有问题。 b4腾讯。这样的题目,无聊时坐着想不难想到,但叫我在现场做题就要骂人了。 |
|
返回顶楼 | |
发表时间:2010-08-31
jeff.key 写道 swen00 写道 zwhc 写道 从海量数据中找出中位数
http://blog.chinaunix.net/u3/94271/showart_2020121.html 这个思路差不多,定义多个连续整形范围的文件 整数范围是0 - 2^32 - 1,一共有4G种取值,映射到256M个区段 然后将文件一部分一部分的读,放入区段文件中... 这个算法应该是最优的。 设映射空间为x,则第m个映射空间的映射大小是(MAXINT / x) * (m, m + 1) 第一次读入文件,但不记录数据,只记录数据在某个映射空间的数量, 经过第一次编历后,可以获得每个区间的统计数, 然后计算,获得中位数的区间。这是一次O(n)的处理。内存空间为常量 第二次处理,设置一个长度为x的投射空间,再一次读入文件, 把数据投入这个空间,同时做累计处理。第二次获得的精细值结合前面一次 的前后位置统计值进行校准,从而获得中位数。第二次处理也是O(n)的运算,内存同样是常量。 所以这是一个O(n)的运算,内存复杂度为常量。至少,题目得解。 一个tricky的东西是,在算法导论中有一个著名算法,求中位数。但难度比这个大很多, 原因是这个题目知道样本空间为有限的整数空间,所以直接投影可以解决所有问题。 b4腾讯。这样的题目,无聊时坐着想不难想到,但叫我在现场做题就要骂人了。 我刚才简单看了一下上面的链接。如果是我自己,我不喜欢用完这2G内存做第一次遍历, 事实上我一般会用几兆内存就算了,因为用几兆内存与2G内存本身没有质的区别。 |
|
返回顶楼 | |
发表时间:2010-09-03
最后修改:2010-09-03
lyw985 写道 10G的整形大概有25亿个整形,想从里面找寻中位数,我有一个最多32n的方法
1.每个数对首位进行异或运算(不懂异或的不用看了)并计2个数量,分别代表了[-2^31~~-1]和[0~2^31-1]的数量,假定为15亿个正数(假定包括0)和10亿个负数,那么答案在[0~2^31-1]范围内 2.哪堆数量比较多,就记录首位数字a(0代表正数,因此a=0),第二遍历的时候就首先满足首位是刚才记录的a,然后再对第二位进行异或运算,并计2个数量,代表了[0~2^30-1]和[2^30~2^31-1]的数量,假定为10亿和5亿,那么答案在[2^30~2^31-1]范围内 3.跟第2步一样,除了首先满足的条件是首位和第2位是0和1(看不懂?整数01开头的整数就代表[2^30~2^31-1]的范围) 4....... 5....... ....... 为什么说是最多32次?因为整数是由32位组成的 为什么说是最多?因为一旦判断不出中位数在哪堆范围内,只需要再来一次,计算这两堆数比较小的堆最大数,和较大堆的最小数,加一下除以2,那就是中位数 到最后一次的话,满足前31位相同,那么就只剩2个数,只要两个数都存在,加一下除以2就是答案,不然??就是那个只存在的数 PS:这里有一点要注意,如果一开始计数时,有一堆超过了整数大小就会导致程序不准确,应该用long型计数 (全思路完结) 实际上是一个二分定位, 其实可以四分,八分... 下面简单的举个例子,看看有没有问题: 比如有255字节(数)找出中位字节(就是排序后的第128个字节), 四分的话, 就是两位进行分别 统计, 比如统计出来结果为: 11xxxxxx 55个 10xxxxxx 50个 00xxxxxx 50个 01xxxxxx 100个 很显然,中位数应该在00xxxxxx段内,并且这个段内的第28个字节(从大到小) 再次进行分别统计,比如统计结果为: 0000xxxx 10个 0001xxxx 10个 0010xxxx 10个 0011xxxx 20个 很显然,中位数应该在0010xxxx段内,并且这个段内的第8个字节(从大到小) 再次进行分别统计,比如统计结果为: 001000xx 1个 001001xx 4个 001010xx 3个 001011xx 2个 很显然,中位数应该在001001xx段内,并且这个段内的第3个字节(从大到小) 再次进行分别统计,比如统计结果为: 00100100 1个 00100101 1个 00100110 2个 00100111 0个 00100101就是我们要找的中位字节 |
|
返回顶楼 | |
发表时间:2010-09-07
最讨厌算法题
|
|
返回顶楼 | |
发表时间:2010-09-07
lyw985 写道 10G的整形大概有25亿个整形,想从里面找寻中位数,我有一个最多32n的方法
1.每个数对首位进行异或运算(不懂异或的不用看了)并计2个数量,分别代表了[-2^31~~-1]和[0~2^31-1]的数量,假定为15亿个正数(假定包括0)和10亿个负数,那么答案在[0~2^31-1]范围内 2.哪堆数量比较多,就记录首位数字a(0代表正数,因此a=0),第二遍历的时候就首先满足首位是刚才记录的a,然后再对第二位进行异或运算,并计2个数量,代表了[0~2^30-1]和[2^30~2^31-1]的数量,假定为10亿和5亿,那么答案在[2^30~2^31-1]范围内 3.跟第2步一样,除了首先满足的条件是首位和第2位是0和1(看不懂?整数01开头的整数就代表[2^30~2^31-1]的范围) 4....... 5....... ....... 为什么说是最多32次?因为整数是由32位组成的 为什么说是最多?因为一旦判断不出中位数在哪堆范围内,只需要再来一次,计算这两堆数比较小的堆最大数,和较大堆的最小数,加一下除以2,那就是中位数 到最后一次的话,满足前31位相同,那么就只剩2个数,只要两个数都存在,加一下除以2就是答案,不然??就是那个只存在的数 PS:这里有一点要注意,如果一开始计数时,有一堆超过了整数大小就会导致程序不准确,应该用long型计数 (全思路完结) 你这个是建议是两个数量不一样的基础上的,假设25亿数中,有12.5亿的正数,12.5亿的负数时,你怎么办? |
|
返回顶楼 | |
发表时间:2010-09-07
最后修改:2010-09-07
yangguo 写道 能不能画下图啊,看不明白你说什么?
我不善于画这类图,如果是草图还行 其实我想这个问题我与lyw985等几位朋友讨论得很清楚了,你可以将我们的贴子连起来读,后面都具有详细的描述。 总体的思路就是说查找中位数是个很特别的算法,他并不需要排序,只需要找出那些比它大,那些比它小就行了,总体说来,时间复杂度为O(n)的 1-100之间为什么55.5是中位数,并不需要将1-100全部排好序并求出它是最中间的。 而是因为1-10间有10位数,11-20有10位数,,,91-100也有10位数。 你能得到一个分布为10,10,...,10的数组。 中位数在哪里,有了这个分布数组,我想找起来是件非常简单的事了。 |
|
返回顶楼 | |
发表时间:2010-09-08
最后修改:2010-09-08
蔡华江 写道 yangguo 写道 能不能画下图啊,看不明白你说什么?
我不善于画这类图,如果是草图还行 其实我想这个问题我与lyw985等几位朋友讨论得很清楚了,你可以将我们的贴子连起来读,后面都具有详细的描述。 总体的思路就是说查找中位数是个很特别的算法,他并不需要排序,只需要找出那些比它大,那些比它小就行了,总体说来,时间复杂度为O(n)的 1-100之间为什么55.5是中位数,并不需要将1-100全部排好序并求出它是最中间的。 而是因为1-10间有10位数,11-20有10位数,,,91-100也有10位数。 你能得到一个分布为10,10,...,10的数组。 中位数在哪里,有了这个分布数组,我想找起来是件非常简单的事了。 有5个数,{1, 2, 100, 9999, 10000},请问中位数是什么? |
|
返回顶楼 | |
发表时间:2010-09-08
最后修改:2010-09-08
jeff.key 写道 蔡华江 写道 yangguo 写道 能不能画下图啊,看不明白你说什么?
我不善于画这类图,如果是草图还行 其实我想这个问题我与lyw985等几位朋友讨论得很清楚了,你可以将我们的贴子连起来读,后面都具有详细的描述。 总体的思路就是说查找中位数是个很特别的算法,他并不需要排序,只需要找出那些比它大,那些比它小就行了,总体说来,时间复杂度为O(n)的 1-100之间为什么55.5是中位数,并不需要将1-100全部排好序并求出它是最中间的。 而是因为1-10间有10位数,11-20有10位数,,,91-100也有10位数。 你能得到一个分布为10,10,...,10的数组。 中位数在哪里,有了这个分布数组,我想找起来是件非常简单的事了。 有5个数,{1, 2, 100, 9999, 10000},请问中位数是什么? 以{1, 2, 100, 9999, 10000}为例 根据一定的算法,可以得出 1-9为2个,10-99有0个,100-999有1个,1000-9999有1个,10000-99999有1个, 有了这个分布数组,你能得到中位数的分布区间在哪里? 当然在100-999。。 然后对100-999排序查找中位数就行了 |
|
返回顶楼 | |