以文本方式查看主题

-  计算机科学论坛  (http://bbs.xml.org.cn/index.asp)
--  『 计算机考研交流 』   (http://bbs.xml.org.cn/list.asp?boardid=67)
----  DS排序难题3道……  (http://bbs.xml.org.cn/dispbbs.asp?boardid=67&rootid=&id=41294)


--  作者:teng_t1986
--  发布时间:12/16/2006 6:27:00 PM

--  DS排序难题3道……
都是习题指导上的增补题


[B]1.A,B为两个长度为n的有序数组,在O(logn)时间内求A并B的中值(习题集P224,习题7.13)注意这题和06那到真题不一样的。

2.已知定值K和长度为n的数组,在O(n^2)时间内检验是否存在三个数之和为K,这题我怎么想都要O(n^2logn)的时间,郁闷……习题集P225

3.一数组中只有0,1,2三种数,在O(logn)时间内排序,这题和荷兰国旗问题是一样的,我觉得最少也得O(n)那,不知道O(logn)怎么来的……[/B]

PS:我下载了最新的习题指导勘误,这三题都没有。

望有人能给出解答,只要算法思想即可,不必写程序了。谢谢!


--  作者:Logician
--  发布时间:12/16/2006 6:41:00 PM

--  
第一题和06真题有什么不同?是说在“并”的时候会消除重复元素吗?

第三题我认为不可能在O(logn)的时间能完成。随便找一个反例:如果原始数组是0,1,2,0,1,2,0,1,2,....这样的形式,那么要把它变成有序(无论正序还是倒序)都需要修改O(n)个单元,怎么可能在O(logn)的时间能完成呢?


--  作者:teng_t1986
--  发布时间:12/16/2006 8:03:00 PM

--  
不是的,06整体是求中位数,如1111111156的中位数是1,
但那道题是求中值,如1111111156的中值是5……
我觉得这几道题都有问题……郁闷无比
--  作者:teng_t1986
--  发布时间:12/16/2006 8:07:00 PM

--  
第2道题,先排序:O(nlogn),在取一个数,用二分法查第二个数,nlogn,得出n^2个数(无序),如果对每个n^2中的数用二分法查n中的数,要n^2logn,如果用n中的每个数查n^2的数,得先对n^2中的数排序,又是n^2log(n^2)=2n^2logn,不排序的话则要n^3……怎么都不可能n^2啊………………
--  作者:teng_t1986
--  发布时间:12/16/2006 8:11:00 PM

--  
07年要考这样的题怎么办?555
关键是勘误表上没说这几题有错!!难道真的还有别的我没想到的办法?
--  作者:Supremgoooo
--  发布时间:12/16/2006 9:02:00 PM

--  
1,3不会,

2提示:先排序,然后固定一个数,其余两个依次二分查找。


--  作者:teng_t1986
--  发布时间:12/16/2006 11:30:00 PM

--  
嗯……有道理,那就是n*logn*logn了,的确是小于n^2的算法。
没想到居然会是这样
谢谢啦!
--  作者:chenminyi
--  发布时间:12/17/2006 12:29:00 PM

--  
以下是引用Supremgoooo在2006-12-16 21:02:00的发言:
1,3不会,

2提示:先排序,然后固定一个数,其余两个依次二分查找。


如何两次二分查找?固定一个数之后能找第二个数吗???

我看是先固定一个数,接下来用递归的方法找到两个数的和满足要求的两个数,我计算过,复杂度为n,所以总的复杂度刚好是n*n。真的不知道怎样写出两个依次二分查找,其复杂度是log(n)*log(n)的


--  作者:teng_t1986
--  发布时间:12/17/2006 12:34:00 PM

--  
例如1 2 3 4 5 6 7 8 9 10
第一个数取1
第二个数取6
第三个数在2-5中二分,对吗?supremgooo?
--  作者:teng_t1986
--  发布时间:12/17/2006 12:41:00 PM

--  
你那样的话怎么可能n^2?
固定一个数:n
在剩余数中找两个数,就是这题的第二小问,要nlogn
总的时间就要n^2logn了呀??

还是你的意思就是我上面那个帖子中的算法?
那就是n*logn*logn呀,第一个数n,剩下两个数均是二分:logn*logn……
对吗?


--  作者:teng_t1986
--  发布时间:12/17/2006 1:16:00 PM

--  
又想了一下,还是有问题呀……正如chenminyi说的,固定第二个数后如何在固定第三个数?
如:1 3 6 9 13 14 19 50,K=25
第一个数取1,
第二个数取13,
第三个数先在3-9中找,
case1:出现某个数使三个数之和大于25,则直接将第二个数向左二分并重新开始第三个数的查找,…………
case2:所有的第三个数都是总和小于25,则第三个数再从第二个数右边开始二分,如果求得的每个和都小于25,那第二个数还是往左边二分,如果求得的和有的大于25,有的小于25呢?第二个数该怎么办?
而且即便第三个数在3-50中二分查找,如果出现了有的大于25有的小于25的情况呢?第二个数好像还是不好进行准确的移位……
求救啊!chenminyi可不可以给出你的算法稍详细一点的步骤??
还有Supremgooooo,但愿他能回来看看这帖子…………
--  作者:teng_t1986
--  发布时间:12/17/2006 1:25:00 PM

--  
以下是引用chenminyi在2006-12-17 12:29:00的发言:
我看是先固定一个数,接下来用递归的方法找到两个数的和满足要求的两个数,我计算过,复杂度为n,所以总的复杂度刚好是n*n。

用递归的方法找到两个数的和满足要求的两个数”,应该怎么进行?且复杂度是n?


--  作者:Smilingface
--  发布时间:12/17/2006 7:41:00 PM

--  
以下是引用teng_t1986在2006-12-16 18:27:00的发言:
都是习题指导上的增补题

3.一数组中只有0,1,2三种数,在O(logn)时间内排序,这题和荷兰国旗问题是一样的,我觉得最少也得O(n)那,不知道O(logn)怎么来的……[/size][/B]

PS:我下载了最新的习题指导勘误,这三题都没有。

望有人能给出解答,只要算法思想即可,不必写程序了。谢谢!



这个题印错了,可以确定是O(N),张铭在某个地方说过,忘记是哪里了。:-)

--  作者:Supremgoooo
--  发布时间:12/17/2006 10:28:00 PM

--  
那就说详细一点:
假设这三个数是a,b,c,数组长n;

1)a很好办,就是从头开始依次指;
2)当a指定了某一个数后,如果这个数大于k,算法结束;
3)否则考虑b,记b的查找区间下标为bl,br,初始时bl=a+1,br=n-1,b在[bl,br]这个区间内二分查找,直到找到第一个b,使a+b<k,不如果没有找到,考虑下一个a;
4)如果找到,记c的查找区间下标为cl,cr,初始时cl=a+1,cr=n-1,考虑c,c在[cl,cr]这个区间内二分查找,直道找到某一个c,使a+b+c=k,如果没有找到,说明b还是太大了,把br指向b-1,转3);
5)如果找到,则a,b,c是一个解,现在关键是找下一个解:要考虑让b小一点,c大一点;或者b大一点,c小一点。对于第一种情况:由于[bl,b]中的元素都满足a+b<k,所以要试这中间的每一个b,固定了b后,cl指向c+1,转4);对于第二种情况,b的取值应该在[b+1,br]中,依次检查这中间的b,直到a+b〉=k,考虑下一个a,否则c在cr=c-1,转4)

btw:应该没有更好的算法了,5)处的实现可以再修改一下,但是效率不能改,否则就丢失解了。


--  作者:Logician
--  发布时间:12/17/2006 10:42:00 PM

--  
你这个算法似乎是O(n^2 * log n)的。
因为对每一个a,第4步对每一个b,要花O(log n)的时间来找c,然后由于b是一个一个递减的,所以对每一个,要试O(n)个不同的b(从而对每一个a,耗时为O(nlogn)),而a又有n个,所以总时间复杂度是O(n^2 * log n)。
--  作者:teng_t1986
--  发布时间:12/17/2006 10:51:00 PM

--  
to supremgoooo:我也是这么想的,可是有反例啊:

1 3 4 10 19 21 50  K=41,有答案41=1+19+21
a=1,b=10,a+b=11<K,c在3至50中找30,没找到,说明b还是太大了,把br指向b-1,
b=3,c在3至50中找37,未找到,
b不能再减少了,移动a,a=3,
然后b和c都不能取比a小的数,故最后查找失败…………

感觉错误出在4):为什么说“说明b还是太大了”?根据上例,b其实是太小了,此时a=1,b=10,而答案应该a=1,b=19,c=21。。

是不是应该让bl和cl都从1开始找?为什么要是a+1呢?题目说可以有重复元素啊…。
另外,logician说的我也没注意看,还是n^2logn吗?



--  作者:chenminyi
--  发布时间:12/18/2006 12:29:00 AM

--  
先取一个数m,令r = K-m,接下来还有2个数需要确定,其和为r,可以想象一个N*N的矩阵~假设n个数排序后分别为a1~an,如下图
     a1      a2 …  an
a1 2*a1           a1+an
a2         2*a2
.  
.  
an                   2*an

显然可以证明2*ai>=ap + aq,若p<=i且q<=i;2*ai<=ap + aq,若p>=i且q>=i;
这样在2*a1~2*an中二分查找r(即在正方形的对角线上进行二分搜索),使得2*ai <= r <= 2*a(i+1)
由上面的分析可以知道所以的p,q若p<i且q<i或者p>i+1且q>i+1,r!=ap+aq;因此可以在矩阵的其他部分进行查找~假设i=n/2,则一次查找过程在n*n个组合可能去掉了一半的组合可能
令开销函数为T(n*n), 有T(n*n) = 2*T(n*n/4)+logn  /*可以想象为原正方形一下去掉了2个1/4小正方形,需要对剩下的2个小正方形递归查找 */
由master理论可知,T(n*n) = (n*n)^log4(2) = (n*n)^(1/2) = n
所以总的复杂度为n*n

这是我最初的思路,后来想了想,由于每次查找得到的i不一定是n/2,开销函数应修改为       T(n*n) = 2*T(i*(n-i))+logn ,这样下面的递归也不能在对角线上进行查找, 因此算法需要进行修改,不过我想最终的平均复杂度应该还是n*n;

:)


--  作者:chenminyi
--  发布时间:12/18/2006 10:39:00 PM

--  
可以将该算法推广到从n个数中选取m个数其和为K,假设K < cn (c为常数)
则其复杂度为(cn)^logm
--  作者:mxf3306
--  发布时间:12/20/2006 9:19:00 PM

--  
题1我觉得在规定时间内不可能实现。题3已经改过来了。
--  作者:teng_t1986
--  发布时间:12/22/2006 6:19:00 PM

--  
chenmingyi你写的我没仔细看,不过我已经想出第3题的正确答案了:
a(第一个数)还是一次遍历数组,
b和c统一处理:先b=c=中间数,
然后判断:
if(a+b+c<k){
   if(b==c)
       b往右二分移位;
   else
       二分:一种b往右二分移位,一种c往右二分移位***
}
注意***处进行了二分,所以搜索树是一颗二*树,
但由于该树枝长为logn,所以最后搜索结果数量即叶子节电树为2^logn=n级,
最终总搜索时间代价正好是n^2级。

我想这就是正确答案,星期一想出来的,因为我工作日无法上网,所以一直没公开出来,
不幸的是,今天我又想到了一个反例(其实也不能说是反例),看:

如果在b、c搜索过程中,第一次移b,第二次移c,如此交替,则在此情况下搜索树枝长可能为2logn,但这样的话时间代价为2^(2logn)=n^2…………
又郁闷了。。。

第一题,我想了一种变态的数组情况:
A:11111111111111156
B:11111111111111178
显然中值为6,但似乎不可能在logn时间内找到,如果1的数量极多的话……
但O(n)级的还是很简单的,大家再思考一下吧。


--  作者:lihaocai
--  发布时间:1/10/2007 4:40:00 PM

--  
数据库的题目啊?。。。晕。
--  作者:chenminyi
--  发布时间:1/10/2007 7:53:00 PM

--  
你说的和我就是一样!呵呵~~
W 3 C h i n a ( since 2003 ) 旗 下 站 点
苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
82.031ms