概述
设将n个整数存放到一维数组R中,试设计一个在时间和空间两方面尽可能有效的算法,将R中保有的序列循环左移P(0<P<n)个位置,即将R中的数据由(X0X1……Xn-1)变换为(XpXp+1……Xn-1X0X1……Xp-1)
数据结构考研的题目。网上搜了下,给我看yue了,还是我自己来吧。
这道题目,可以设计出一个时间复杂度为O(n)的非递归原地算法出来,相信时间空间两方面都很难再高效点了。思路如下:
对数组(X0X1……Xn-1)左移p位,我们可以把数组分为((X0X1……Xp-1 | XpXp+1……Xn-1)两部分。
若p<n/2,我们可以选择把(X0X1……Xp-1)和(Xn-pXn-p+1……Xn-1)依次交换,此时数组已经变为(Xn-pXn-p+1……Xn-1 | XpXp+1……Xn-p-1 | X0X1……Xp-1)这三部分。但是最后一部分已经到位了,不需要再操作了,因此需要处理的只有前两部分,即(Xn-pXn-p+1……Xn-1 | XpXp+1……Xn-p-1)这一个小了一截的数组。
诶,那股子“子结构”的感觉是不是出来了?若p>n/2,那就把后面的提到前面即可,操作大差不差。
这个算法抽象来讲,就是一轮一轮地把数组的子串通过元素交换的方式放到它应该的位置,直到换无可换。
下面是代码:
#include <iostream>
#include <algorithm>
using namespace std;
int arr[10] = { 0,1,2,3,4,5,6,7,8,9 };//数组
const int length = 10;//数组长度
//令数组左循环n位
void forth(int lef, int mid, int rig) {//将数组的后(length-n)个元素与前(length-n)个元素依次对调
int i = lef, j = mid + 1;
while (j <= rig)
swap(arr[i++], arr[j++]);
}
void retreat(int lef, int mid, int rig) {//将数组的前n个元素与后n个元素依次对调
int i = mid, j = rig;
while (i >=lef)
swap(arr[i--], arr[j--]);
}
int main() {
unsigned int n;//左移位数
cin >> n;
n %= length;
int lef = 0, mid = n - 1, rig = length - 1;
while (mid >= lef && mid < rig) {
if (mid - lef < rig - mid - 1) {
//当前需要位移的子串长度小于当前处理的子串长度的一半,就直接把这个子串往后交换
retreat(lef, mid, rig);
rig -= (mid - lef + 1);
}
else {
//当前需要位移的子串长度大于当前处理的子串长度的一半,就得把剩下那个小的子串往前交换
forth(lef, mid, rig);
lef += (rig - mid);
}
}
for (int i = 0; i < length; ++i)cout << arr[i] << " ";
cout << endl;
return 0;
}
每次交换都是旧元素和新元素相交换,没有重复交换的情况,因此时间复杂度为O(n);使用的是原地算法,因此空间复杂度为O(1)。
最后
以上就是纯真音响为你收集整理的数组循环左移的O(n)&O(1)算法的全部内容,希望文章能够帮你解决数组循环左移的O(n)&O(1)算法所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复