题目:
有个长度为2n的数组{a1,a2,a3,...,an,b1,b2,b3,...,bn},希望排序后{a1,b1,a2,b2,....,an,bn},请考虑有无时间复杂度o(n),空间复杂度0(1)的解法。
题目来源:此题是去年2013年UC的校招笔试题
思路:解法一、蛮力变换
题目要我们怎么变换,咱们就怎么变换。此题@陈利人也分析过,在此,引用他的思路进行说明。为了便于分析,我们取n=4,那么题目要求我们把
a1,a2,a3,a4,b1,b2,b3,b4
变成
a1,b1,a2,b2,a3,b3,a4,b4
1.1、步步前移
仔细观察变换前后两个序列的特点,我们可做如下一系列操作:
第①步、确定b1的位置,即让b1跟它前面的a2,a3,a4交换:
a1,b1,a2,a3,a4,b2,b3,b4
第②步、接着确定b2的位置,即让b2跟它前面的a3,a4交换:
a1,b1,a2,b2,a3,a4,b3,b4
第③步、b3跟它前面的a4交换位置:
a1,b1,a2,b2,a3,b3,a4,b4
b4已在最后的位置,不需要再交换。如此,经过上述3个步骤后,得到我们最后想要的序列。但此方法的时间复杂度为O(N^2),我们得继续寻找其它方法,看看有无办法能达到题目所预期的O(N)的时间复杂度。
1.2、中间交换
当然,除了如上面所述的让b1,b2,b3,b4步步前移跟它们各自前面的元素进行交换外,我们还可以每次让序列中最中间的元素进行交换达到目的。还是用上面的例子,针对a1,a2,a3,a4,b1,b2,b3,b4
第①步:交换最中间的两个元素a4,b1,序列变成(待交换的元素用粗体表示):
a1,a2,a3,b1,a4,b2,b3,b4
第②步,让最中间的两对元素各自交换:
a1,a2,b1,a3,b2,a4,b3,b4
第③步,交换最中间的三对元素,序列变成:
a1,b1,a2,b2,a3,b3,a4,b4
同样,此法同解法1.1、步步前移一样,时间复杂度依然为O(N^2)。
解法二、完美洗牌算法
举一反三
至此,本章开头提出的问题解决了,完美洗牌算法的证明也证完了,是否可以止步了呢?OH,NO!读者有无思考过下述问题:
1、既然完美洗牌问题是给定输入:a1,a2,a3,……aN,b1,b2,b3,……bN,要求输出:b1,a1,b2,a2,……bN,aN;那么有无考虑过它的逆问题:即给定b1,a1,b2,a2,……bN,aN,,要求输出a1,a2,a3,……aN,b1,b2,b3,……bN ?
2、完美洗牌问题是两手洗牌,假设有三只手同时洗牌呢?那么问题将变成:输入是a1,a2,……aN, b1,b2,……bN, c1,c2,……cN,要求输出是c1,b1,a1,c2,b2,a2,……cN,bN,aN,这个时候,怎么处理?