1.个人之见(C语言)
Eg:对于1 2 3 4 5 6 ,移动1次->6 1 2 3 4 5
可以通过找规律得出:
首位尾元素交换一次位置:6 2 3 4 5 1
然后第二个元素和末尾交换位置:6 1 3 4 5 2
然后第三个元素和末尾交换位置:6 1 2 4 5 3
然后第四个元素和末尾交换位置:6 1 2 3 5 4
然后第五个元素和末尾交换位置:6 1 2 3 4 5完成
每次都要遍历一整个数组
移动大于一次也是一样的,但是要注意,对于6个元素的数组,移动6次和移动0次是等价的
移动7次和移动1次同样是等价的,这里存在一个周期T = 移动次数 % 元素总数
然后元素的交换可以用指针来实现
**begin指针指向第一个元素,*des指针指向末尾元素,然后begin指针每完成一次交换自增1 而des指针不变,仍指向末尾元素,当两个指针相遇时就表面已经完成一次交换 **
核心代码:
int i, temp;
int* begin,*des;
m = m % n;
for (i = 0; i < m; i++)//外循环决定要遍历整个数组的次数
{
int* begin = a;//每次完成整个数组的遍历后,要重置一下指针的指向
int* des = a + n - 1;
while (*begin != *des)//内循环确保每次都遍历到整个数组
{
temp = *begin;
*begin = *des;
*des = temp;
begin++;
}
}
由于每次都要遍历整个数组,所以这种方法的效率不太高,时间复杂度O(N^2)
2.在输入的时候就排好序
还是1 2 3 4 5 6这个例子 m的范围[0,6]不变
移动一次:6 1 2 3 4 5 1最后到了a[1]的位置,2到了a[2]的位置·····6本应该在a[6]的位置,由于会越界,就跑到了a[0]的位置
移动两次:5 6 1 2 3 4 1->a[2] ;2->a[3]·········5->a[6]? No,->a[0],6->a[7]? ->a[1]
移动三次:4 5 6 1 2 3 ············
不难发现,每次要输出的时候,每个元素的最终位置都移动次数m有着更具体的关系:
对于1来说,它最终到了 a[m]的位置,2便到了a[m + 1]的位置,而5->a[m + 4],当m比较大肯定会越界.例如当m=2时 5最后在a[0]上面,6在a[1]上面。这里的0,可以当成 6 % 6 ;1 可以认为7 % 6利用周期性来解决越界问题
所以元素的输入可以先写为:
m = m % n;
scanf("%d",&a[m]);
在第一个元素输入完后,使m++,来输入下一个元素
最终:
m = m % n;
scanf("%d",&a[m]);
m++;
核心代码:
for (int i = 0; i < n; i++)
{
m = m % n;
scanf("%d", &a[m]);
m++;
}
最从0到n打印即可
这种方法时间复杂度O(N)