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)