从ural1082看快速排序

ural1082是个水题,答案简单到可以直接在代码提交框里进行编辑。。。事实上我也这么做了。。于是得了两个compilation error从ural1082看快速排序从ural1082看快速排序
但是,题目简单,并不能说明此题没有含量,相反,这个题很有含量。
这道题考察了对快速排序的理解。题目的大概意思就是,给出一段快排代码,代码中添加变量c统计指针的移动次数,如果移动次数等于(N*N+3*N-4)/2,然后解题的人就可以把"Beutiful Vasilisa"娶回家了。。。要求,找出一个数的序列,使得移动次数等于(N*N+3*N-4)/2。

这个题的通过率很高,但是我在看discuss的时候,并没有发现正确的题解。
人们认为,给出一个有序序列,导致快排的效率退化到了和冒泡一样的情况的时候,会满足题设。
对,但并不完全正确。
所谓的退化成O(n^2),并不是完全的由于序列有序所导致的。而是说,递归过程中,产生的整棵树,退化为了近似单枝树的情况,也就是序列划分为n-1和1两个序列,且,子序列与目的序列反序。如果取的是中间的数或者是随机数的话,就算有序,也不会退化。

那么这道题的解法究竟是什么呢?可以说是歪打正着了吧。。因为此题恰好取得是最左边的那个数。
只要是反序序列,退化为单枝树之后,每次比较的次数依次是n+2,(加2是因为需要i,j两个指针交叉,这是循环退出条件)n+1,n...2。求和,恰好是(N+2+2)(N-1)/2 = (N*N+3*N-4)/2。
但是如果题目所取的数轴为序列中间的数的话,那这种方法则不会得到正确的解。
此时就需要构造一个序列,保证,每个子序列的中间数为该序列的最大数或者最小数,这样就可以保证该递归树退化为单枝树。
构造方法很简单,递归即可。
posted @ 2011-04-26 18:26  dk647  阅读(624)  评论(0编辑  收藏  举报