您的位置:首页 > 其它

数组旋转的高效算法

2008-02-29 16:02 344 查看
学校网速超慢,难得有机会用自己的博客。等以后条件好点了,一定多写点心得,和大家一起交流,希望大家常来。

现在向大家介绍一个原来在论坛上碰到过的一个问题,题目很短,大致如下:

一维数组,数组长度为N,求将数组循环右移M个长度的算法。要求:

1 时间复杂度为O(N)

2 空间复杂度为O(1)

下面给出我的解决方案:


#include <iostream>


using namespace std;




void RightMove(int a[],int length,int moveSize)




...{




/**//*


本算法采用跳跃移动的方式。例如:


a[4] = {1,2,3,4}循环右移2位,先从下标startPos = 3 开始 将a[3]保存到temp中


,移动下一个位置a[1]到a[3]中


然后startPos-- 从 startPos = 2 开始 将a[2]保存到temp中。。。。


简单地说,就是从一个初始位置开始,移动一组数据,这组数据都在最终的位置。


*/




//本算法时间为O(n),空间为O(1);




int count = 0;


int startPos,nextPos,curPos,endPos;


// startPos 开始移动的位置,初值为N-1


//nextPos 下一个要移动的位置


//curPos 当前移动的位置


//endPos 结束的位置


int temp;




moveSize %= length;




startPos = length - 1;


endPos = startPos - moveSize;


while (count < length && startPos > endPos)




...{


curPos = startPos;


nextPos = (startPos - moveSize + length) % length;


temp = a[startPos];




while(nextPos!=startPos)




...{


a[curPos] = a[nextPos];


curPos = nextPos;


nextPos = (curPos - moveSize + length) % length;


count++;


}


if (curPos != startPos)




...{


a[curPos] = temp;


count++;


}




startPos--;


}


}




void DisPlayArray(int a[],int size)




...{


for (int i = 0; i < size; i++)


cout < < a[i] < < endl;


}




int main()




...{




int a[9] = ...{1,2,3,4,5,6,7,8,9};




RightMove(a,9,4);


DisPlayArray(a,9);




return 0;


}



另外,还有一个比较经典的方法。虽然效率比上面的要低点,但其思想的确很精辟!因为它的算法很简单,

假设数组长度为len+1,循环右移m位。可以分以下3个步骤来解决:

1)Reverse( a[], 0, len-m )

2)Reverse( a[], len-m+1, len )

3)Reverse( a[], 0, len )

Reverse( a[], i, j ) 完成的就是数组下标从 i 到 j 的这个序列的 转置

举各例子,a[5] = {1,2,3,4,5}; m = 2

Reverse( a, 0, 2 ) 序列 = {3, 2, 1, 4, 5 }

Reverse( a, 3, 4) 序列 = {3,2,1,5,4 }

Reverse( a, 0, 4) 序列 = {4,5,1,2,3}

数组的确是循环右移了2个单位,怎么样,是不是很有趣阿?
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐