数组移动算法算法实现
对于有n个元素的数组 int a[n]={....};写一个高效算法将数组内容循环左移m位
比如: int a[6] ={1,2,3,4,5,6} ,循环左移3位得到结果{456123},
要求:
1不允许另外申请数组空间,但可以申请少许变量
2不允许采用每次左移
//////////////////////////////////////////////
算法的基本思想如下:
设有一个包含8个数的数组 int a[8] = {1, 2, 3, 4, 5, 6, 7, 8}; 将其内容循环左移3位,即左移后的
结果是4, 5, 6, 7, 8, 1, 2, 3。
从上例可以看出,将1,2,3移到了数组的最后,从4开始,直到8都往前移动了3个位置。因此我们可设想
将1,2,3看成一个整体先和4, 5, 6交换, 再和7, 8交换。
第一次交换的结果:
4, 5, 6, 1, 2, 3, 7, 8
由于7,8只有两位,因此第二次交换只和1,2,3中的1,2进行交换。结果如下:
4, 5, 6, 7, 8, 3, 1, 2。
可以看出,前五位已经满足了最终结果,只有后3位还不满足最终结果。但是只要将3, 1, 2看成一个
子数组,再将这个子数组循环左移1位,即可变成1, 2, 3。
因此在移动元素时可将要左移的m位看成一个整体(如上例中的1, 2, 3),依次和它后面的相同位数的
数组元素交换,如果后面的元素不足m位,假设为t位,t < m,那么只交换t位,这样,前面的数组元素(前n - m个元素一定满足条件)。
最后将后面m个元素看成一个子数组,再对其进行循环左移m - n % m位。
算法的时间复杂度为O(n),空间复杂度为O(1)。
c实现如下(move_array为算法实现函数,并带有测试用例):
比如: int a[6] ={1,2,3,4,5,6} ,循环左移3位得到结果{456123},
要求:
1不允许另外申请数组空间,但可以申请少许变量
2不允许采用每次左移
//////////////////////////////////////////////
算法的基本思想如下:
设有一个包含8个数的数组 int a[8] = {1, 2, 3, 4, 5, 6, 7, 8}; 将其内容循环左移3位,即左移后的
结果是4, 5, 6, 7, 8, 1, 2, 3。
从上例可以看出,将1,2,3移到了数组的最后,从4开始,直到8都往前移动了3个位置。因此我们可设想
将1,2,3看成一个整体先和4, 5, 6交换, 再和7, 8交换。
第一次交换的结果:
4, 5, 6, 1, 2, 3, 7, 8
由于7,8只有两位,因此第二次交换只和1,2,3中的1,2进行交换。结果如下:
4, 5, 6, 7, 8, 3, 1, 2。
可以看出,前五位已经满足了最终结果,只有后3位还不满足最终结果。但是只要将3, 1, 2看成一个
子数组,再将这个子数组循环左移1位,即可变成1, 2, 3。
因此在移动元素时可将要左移的m位看成一个整体(如上例中的1, 2, 3),依次和它后面的相同位数的
数组元素交换,如果后面的元素不足m位,假设为t位,t < m,那么只交换t位,这样,前面的数组元素(前n - m个元素一定满足条件)。
最后将后面m个元素看成一个子数组,再对其进行循环左移m - n % m位。
算法的时间复杂度为O(n),空间复杂度为O(1)。
c实现如下(move_array为算法实现函数,并带有测试用例):
#include <stdio.h>
void swap(int *a, int *b)
{
int x;
x = *a;
*a = *b;
*b = x;
}
//这个函数为算法实现部分
/////////////////////////////////////////
void move_array(int data[], int n, int m)
{
int i, j;
m = m % n;
if(m == 0) return;
for(i = 0; i < n - m; i += m)
{
for(j = i; j < i + m && j < n - m; j++)
{
swap(&data[j], &data[j + m]);
}
}
move_array(data + n - m, m, m - n % m);
}
/////////////////////////////////////////
int main()
{
int data1[] = {1, 2, 3, 4, 5, 6, 7, 8};
int data2[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14};
int data3[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
int data4[] = {1, 2, 3, 4, 5, 6};
int data5[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18};
int i;
move_array(data1, 8, 5);
for(i = 0; i < 8; i++)
printf("%d ", data1[i]);
printf("\n");
move_array(data2, 14, 18);
for(i = 0; i < 14; i++)
printf("%d ", data2[i]);
printf("\n");
move_array(data3, 9, 3);
for(i = 0; i < 9; i++)
printf("%d ", data3[i]);
printf("\n");
move_array(data4, 6, 3);
for(i = 0; i < 6; i++)
printf("%d ", data4[i]);
printf("\n");
move_array(data5, 18, 17);
for(i = 0; i < 18; i++)
printf("%d ", data5[i]);
printf("\n");
return 0;
}
void swap(int *a, int *b)
{
int x;
x = *a;
*a = *b;
*b = x;
}
//这个函数为算法实现部分
/////////////////////////////////////////
void move_array(int data[], int n, int m)
{
int i, j;
m = m % n;
if(m == 0) return;
for(i = 0; i < n - m; i += m)
{
for(j = i; j < i + m && j < n - m; j++)
{
swap(&data[j], &data[j + m]);
}
}
move_array(data + n - m, m, m - n % m);
}
/////////////////////////////////////////
int main()
{
int data1[] = {1, 2, 3, 4, 5, 6, 7, 8};
int data2[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14};
int data3[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
int data4[] = {1, 2, 3, 4, 5, 6};
int data5[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18};
int i;
move_array(data1, 8, 5);
for(i = 0; i < 8; i++)
printf("%d ", data1[i]);
printf("\n");
move_array(data2, 14, 18);
for(i = 0; i < 14; i++)
printf("%d ", data2[i]);
printf("\n");
move_array(data3, 9, 3);
for(i = 0; i < 9; i++)
printf("%d ", data3[i]);
printf("\n");
move_array(data4, 6, 3);
for(i = 0; i < 6; i++)
printf("%d ", data4[i]);
printf("\n");
move_array(data5, 18, 17);
for(i = 0; i < 18; i++)
printf("%d ", data5[i]);
printf("\n");
return 0;
}