经典算法 之 子数组换位问题

本文探讨了一种子数组换位问题的有效解决方案,采用分治法和三次反转算法,确保算法的时间复杂度为O(n),并仅使用O(1)的辅助空间。

子数组换位问题

设a[0:n-1]是一个有n个元素的数组,k(0<=k<=n-1)是一个非负整数。
试设计一个算法将子数组a[0:k]与a[k+1,n-1]换位。要求算法在最坏情况下耗时O(n),且只用到O(1)的辅助空间。

初步思考:最简单的方法就是循环(n-k-1)次,将a数组的末尾数字插入到a[0]之前。

具体做法:
(1) 首先开辟一个额外空间temp用于存放每一次a数组的末尾数据。
(2) temp <- a[n-1]
(3) 将a[0: n-2] 每个数据都依次向后移动一位赋值给a[1: n-1]。
(4) a[0] <- temp
(5) 循环执行(2) -(4) 步 (n-k+1)次。

代价分析: 时间代价—— O((n-1)*(n-k+1)) 即O(n^2)数量级;空间代价: O(1)

我们仔细想想还有没有更快的办法呢?试想一下,如果a[0 : k] 与 a[k+1 : n-1] 正好长度相等,则可以直接一一对应交换即可。 当然,这道题的难点就在于k并不一定是a数组的中间位置。即便如此,但是仍然可以交换:

采用分治算法

当v[k]左边子数组的长度等于右边的子数组长度时,直接将两个子数组对应的元素互换即可
当左边子数组长度小于右边子数组长度时,将左边子数组与右边子数组右边的等长子数组对换,再对结果递归调用对换函数
当右边子数组长度小于左边子数组长度时,将右边子数组与左边子数组左边的等长子数组对换,再对结果递归调用对换函数

通过分析,可知只需要利用保存元素对换时的交换空间即可,空间复杂度为O(1),子数组对换时时间复杂度不会超过O(n)

代码如下:

//交换数组的两段大小相等的范围的对应数据  
//
利用Java编写的几种经典问题算法1.a[0:n-1]是一个有n个元素数组,k(0<=k<=n-1)一个非负整数。 试设计一个算法子数组a[0:k]与a[k+1,n-1]换位。要求算法在最坏情况下耗时O(n),且只用到O(1)的辅助空间。 2.在一个圆形操场的四周摆放着n堆石。现要将石有次序地合并成一堆。规定每次只能选相邻的2堆石合并成新的一堆,并将新的一堆石记为该次合并的得分。试设计一个算法,计算出将n堆石合并成一堆的最小得分和最大得分,并分析算法的计算复杂性。 3.磁盘上有n个文件f1,f2,…,fn,每个文件占用磁盘上的1个磁道。这n个文件的检索概率分别是p1,p2,…,pn,且 =1。磁头从当前磁道移到被检信息磁道所需的时间可用这2个磁道之间的径向距离来度量。如果文件fi存放在第i道上,1≦i≦n,则检索这n个文件的期望时间是对于所有的i<j,time+=pi*pj*d(i,j) 。其中d(i,j)是第i道与第j道之间的径向距离|i-j|。磁盘文件的最优存储问题要求确定这n个文件在磁盘上的存储位置,使期望检索时间达到最小。试设计一个解决此问题算法,并分析算法的正确性与计算复杂度。 4.最小重量机器设计问题某一机器由n个部件组成,每一种部件可以从m个不同的供应商处购得。wij是从供应商j处购得的部件i的重量,cij是相应的价格。试设计一个算法,给出总价格不超过c的最小重量机器设计
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值