微软面试题求解

gegeda2099 2011-08-03 10:59:32
现有10000个随机数,求出第50个大小的数,要求时间复杂度为O(kn)(k为1、2、3、4等整数)
...全文
186 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
luciferisnotsatan 2011-08-03
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 xuchenshabi1 的回复:]

额。。。恕我想的简单了,好像时间复杂度为O(n)的查找只有顺序查找法啊,找50编,近似O(50n),这么简单吗
[/Quote]
有O(kn)的排序算法,当然,对输入值有一定显示。这随机数是不是整数?
ganjianh8 2011-08-03
  • 打赏
  • 举报
回复
n是什么?
问题是不是应该为
现有n个随机数,求出第50个大小的数,要求时间复杂度为O(kn)(k为1、2、3、4等整数)
xuchenshabi1 2011-08-03
  • 打赏
  • 举报
回复
额。。。恕我想的简单了,好像时间复杂度为O(n)的查找只有顺序查找法啊,找50编,近似O(50n),这么简单吗
icansaymyabc 2011-08-03
  • 打赏
  • 举报
回复
先准备一个尺寸为 50 的顺序表(或者堆什么的看你喜欢神马数据结构了),

依次读入随机数,如它小于表中最后一个数则抛弃,否则插入顺序表中正确位置,并抛弃表中最后一个数。

完了返回表中最后一个数作为答案。

算法复杂度 O(kn),k=50*log50
hndcwynui 2011-08-03
  • 打赏
  • 举报
回复
第k大的数-选择算法

可以参考http://s99f.blog.163.com/blog/static/351183652009499403032/

算法导论书 第9章第2节也有这个问题的解答

利用类似快排中划分方法可以在O(n) 找到第k个大小的数
jackyjkchen 2011-08-03
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 xyh211 的回复:]

7楼的前辈,我怎么看怎么想,好像您的代码的结果都是统计0到255这些数出现的次数
[/Quote]
这就是计数排序的思想,最后从小到大分别输出,不就是排序了么

0~255是举个例子,你也可以0~65535(ushort范围),再大可能就不适合用这种非交换排序了
gegeda2099 2011-08-03
  • 打赏
  • 举报
回复
7楼的前辈,我怎么看怎么想,好像您的代码的结果都是统计0到255这些数出现的次数
chengys520 2011-08-03
  • 打赏
  • 举报
回复
学习了
gegeda2099 2011-08-03
  • 打赏
  • 举报
回复
2楼的前辈能否细说一下您的想法
lazi2008 2011-08-03
  • 打赏
  • 举报
回复
不知道什么是时间的复杂度。。
gegeda2099 2011-08-03
  • 打赏
  • 举报
回复
对了随机数现在假定为整数
gegeda2099 2011-08-03
  • 打赏
  • 举报
回复
这么多牛人!真是学习了
jackyjkchen 2011-08-03
  • 打赏
  • 举报
回复
这一题含简单啊,计数排序或鸽巢排序,这种非交换排序的复杂度就是O(n),比快速排序这样的交换排序快,但需要额外空间,思想上就是1楼那样的,参考代码

这个是针对字节串的,比字节更大范围的,要相应增加缓冲区

void PigeonholeSort(BYTE *array, int length)
{
int b[256] = {0};
int i,k,j = 0;
for(i=0; i<length; i++)
b[array[i]]++;
for(i=0; i<256; i++)
for(k=0; k<b[i]; k++)
array[j++] = i;
}

luciferisnotsatan 2011-08-03
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 hacqing 的回复:]
lz提的问题值得怀疑呀. 时间复杂度O(kn) k = 1, 2, 3...(与n无关系数)?
这是什么时间复杂度表达式呀, 堪称micro的面试题?
[/Quote]
说不定,很多去面的人看到 O(n),以为遍历一次。结果没办法,只能改kn了。
hacqing 2011-08-03
  • 打赏
  • 举报
回复

lz提的问题值得怀疑呀. 时间复杂度O(kn) k = 1, 2, 3...(与n无关系数)?
这是什么时间复杂度表达式呀, 堪称micro的面试题?
1.烧一根不均匀的绳,从头烧到尾总共需要1个小时。现在有若干条材质相同的绳子,问如何用烧绳的方法来计时一个小时十五分钟呢? 2.你有一桶果冻,其中有黄色、绿色、红色三种,闭上眼睛抓取同种颜色的两个。抓取多少个就可以确定你肯定有两个同一颜色的果冻? 3.如果你有无穷多的水,一个3公升的提捅,一个5公升的提捅,两只提捅形状上下都不均匀,问你如何才能准确称出4公升的水? 4.一个岔路口分别通向诚实国和说谎国。来了两个人,已知一个是诚实国的,另一个是说谎国的。诚实国永远说实话,说谎国永远说谎话。现在你要去说谎国,但不知道应该走哪条路,需要问这两个人。请问应该怎么问? 5.12个球一个天平,现知道只有一个和其它的重量不同,问怎样称才能用三次就找到那个球。13个呢?(注意此题并未说明那个球的重量是轻是重,所以需要仔细考虑) 6.在9个点上画10条直线,要求每条直线上至少有三个点? 7.在一天的24小时之中,时钟的时针、分针和秒针完全重合在一起的时候有几次?都分别是什么时间?你怎样算出来的? 8.怎么样种植4棵树木,使其中任意两棵树的距离相等? 第一组题答案: 1)三根绳,第一根点燃两端,第二根点燃一端,第三根不点 第一根绳烧完(30分钟)后,点燃第二根绳的另一端,第二根绳烧完(45分钟)后,点燃第三根绳子两端,第三根绳烧完(1小时15分)后,计时完成 2)根据抽屉原理,4个 3)3升装满;3升-〉5升(全注入);3升装满;3升-〉5升(剩1升);5升倒掉;3升-〉5升(注入1升);3升装满;3升-〉5升;完成(另:可用回溯法编程求解) 4)问其中一人:另外一个人会说哪一条路是通往诚实国的?回答者所指的那条路必然是通往说谎国的。 5)12个球: 第一次:4,4 如果平了: 那么剩下的球中取3放左边,取3个好球放右边,称: 如果左边重,那么取两个球称一下,哪个重哪个是次品,平的话第三个重,是次品,轻的话同理 如果平了,那么剩下一个次品,还可根据需要称出次品比正品轻或者重 如果不平: 那么不妨设左边重右边轻,为了便于说明,将左边4颗称为重球,右边4颗称为轻球,剩下4颗称为好球 取重球2颗,轻球2颗放在左侧,右侧放3颗好球和一颗轻球 如果左边重 称那两颗重球,重的一个次品,平的话右边轻球次品 如果右边重 称左边两颗轻球,轻的一个次品 如果平 称剩下两颗重球,重的一个次品,平的话剩下那颗轻球次品 13个球: 第一次:4,4,如果平了 剩5颗球用上面的方法仍旧能找出次品,只是不能知道次品是重是轻 如果不平,同上 6) o o o o o o o o o 7) 23次,因为分针要转24圈,时针才能转1圈,而分针和时针重合两次之间的间隔显然>1小时,它们有23次重合机会,每次重合中秒针有一次重合机会,所以是23次 重合时间可以对照手表求出,也可列方程求出 8) 在地球表面种树,做一个地球内接的正四面体,内接点即为所求
现网络上,此类题目的求解多以C,C++为主,面C#代码鲜见. 附件为本人以C#版控制台程序对各试题的求解,希望大家 相互学习,以抛砖引玉. 例如: 微软 在一天的24小时之中,时钟的时针、分针和秒针完全重合在一起的时候有几次? 都分别是什么时间?你怎样算出来的? C#代码 private void ThePlaceIsSameAbout() { const double dAbout = 2 / 360.0; const double dMinAbout = 1799 / 3600.0; const double dMaxAbout = 1801 / 3600.0; for (double i = 0; i <12; i++) for(double j=0;j<60;j++) for(double k=0;k<60;k++) { double HourPlace =i/12+j/60/12+k /60/60/12; double MinutePlace =j/60+k/60/60; double SecondPlace = k/60; //时分秒相差<=0度 原题 if (Math.Abs(HourPlace - MinutePlace) <= 0 && Math.Abs(MinutePlace - SecondPlace) <= 0 && Math.Abs(HourPlace - SecondPlace) <= 0) { Console.WriteLine("三针完全一致:{0}时{1}分{2}秒", i, j, k); //Console.WriteLine("{0}时{1}分{2}秒", i+12, j, k); } //时分秒相差<=2度 扩展1 if (Math.Abs(HourPlace - MinutePlace) <= dAbout && Math.Abs(MinutePlace - SecondPlace) <= dAbout && Math.Abs(HourPlace - SecondPlace) <= dAbout) { Console.WriteLine("三针几乎一致:{0}时{1}分{2}秒", i, j, k); //Console.WriteLine("{0}时{1}分{2}秒", i+12, j, k); } //时分几乎水平 时分相差<=0.1度 扩展2 if (Math.Abs(HourPlace - MinutePlace) <= dMaxAbout && Math.Abs(HourPlace - MinutePlace) >= dMinAbout) { Console.WriteLine("时分几乎水平:{0}时{1}分{2}秒", i, j, k); //Console.WriteLine("{0}时{1}分{2}秒", i+12, j, k); } } } 执行结果: 三针完全一致:0时0分0秒 三针几乎一致:0时0分0秒 时分几乎水平:0时32分43秒 时分几乎水平:0时32分44秒 时分几乎水平:1时38分10秒 时分几乎水平:1时38分11秒 时分几乎水平:1时38分12秒 三针几乎一致:2时11分11秒 时分几乎水平:2时43分38秒 时分几乎水平:2时43分39秒 时分几乎水平:3时49分5秒 时分几乎水平:3时49分6秒 时分几乎水平:4时54分32秒 时分几乎水平:4时54分33秒 时分几乎水平:5时59分59秒 时分几乎水平:6时0分0秒 时分几乎水平:6时0分1秒 时分几乎水平:7时5分27秒 时分几乎水平:7时5分28秒 时分几乎水平:8时10分54秒 时分几乎水平:8时10分55秒 时分几乎水平:9时16分21秒 时分几乎水平:9时16分22秒 三针几乎一致:9时48分49秒 时分几乎水平:10时21分48秒 时分几乎水平:10时21分49秒 时分几乎水平:10时21分50秒 时分几乎水平:11时27分16秒 时分几乎水平:11时27分17秒 题目:求1+2+…+n, 要求不能使用乘除法、for、while、if、else、switch、case等关键字以及条件判断语句(A?B:C) C#求解(与C,C++思路不同的另一种思路) private int Fact(int n) { //1+2+…+n=n*(n+1)/2=(n^2+n)/2; int[,] array=new int[n,n]; int NPower2 = array.Length; //NPower2=n*n int iElement = NPower2 + n;//iElement=(n^2+n) int iFact = iElement >> 1; //iFact=(n^2+n)/2 return iFact; } private int Fact_Extend(int n) //扩展,也不用加法 { //1+2+…+n=n*(n+1)/2 int[,] array = new int[n, n+1]; int iElement = array.Length; //NPower2=n*(n+1) int iFact = iElement >> 1; //iFact=n*(n+1)/2 return iFact; } 另包括以下题目 判断整数序列是不是二元查找树的后序遍历结果 题目:输入一个整数数组,判断该数组是不是某二元查找树的后序遍历的结果。 如果是返回true,否则返回false。 例如输入5、7、6、9、11、10、8,由于这一整数序列是如下树的后序遍历结果: 8 / \ 6 10 / \ / \ 5 7 9 11 因此返回true。 如果输入7、4、6、5,没有哪棵树的后序遍历的结果是这个序列,因此返回false 把二元查找树转变成排序的双向链表 题目: 输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表。 要求不能创建任何新的结点,只调整指针的指向。 10 / \ 6 14 / \ / \ 4 8 12 16 转换成双向链表 4=6=8=10=12=14=16。 n个数字(0,1,…,n-1)形成一个圆圈,从数字0开始, 每次从这个圆圈中删除第m个数字(第一个为当前数字本身,第二个为当前数字的下一个数字)。 当一个数字删除后,从被删除数字的下一个继续删除第m个数字。 求出在这个圆圈中剩下的最后一个数字。 题目:输入一个已经按升序排序过的数组和一个数字, 在数组中查找两个数,使得它们的和正好是输入的那个数字。 要求时间复杂度是O(n)。如果有多对数字的和等于输入的数字,输出任意一对即可。 例如输入数组1、2、4、7、11、15和数字15。由于4+11=15,因此输出4和11。 求子数组的最大和 题目: 输入一个整形数组,数组里有正数也有负数。 数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。 求所有子数组的和的最大值。要求时间复杂度为O(n)。 例如输入的数组为1, -2, 3, 10, -4, 7, 2, -5,和最大的子数组为3, 10, -4, 7, 2, 因此输出为该子数组的和18。 .....

69,382

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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