1008 数组元素循环右移问题
题目
一个数组 A A A 中存有 N ( > 0 ) N(>0) N(>0)个整数,在不允许使用另外数组的前提下,将每个整数循环向右移 M ( ≥ 0 ) M(≥0) M(≥0)个位置,即将A中的数据由 ( A 0 A 1 ⋅ ⋅ ⋅ A N − 1 ) ({A_0}{A_1} \cdot \cdot \cdot {A_{N - 1}}) (A0A1⋅⋅⋅AN−1)变换为 ( A N − M ⋅ ⋅ ⋅ A N − 1 A 0 ⋅ ⋅ ⋅ A N − M − 1 ) ({A_{N - M}} \cdot \cdot \cdot {A_{N - 1}}{A_0} \cdot \cdot \cdot {A_{N - M - 1}}) (AN−M⋅⋅⋅AN−1A0⋅⋅⋅AN−M−1)(最后M个数循环移至最前面的M个位置)。如果需要考虑程序移动数据的次数尽量少,要如何设计移动的方法?
输入格式:
每个输入包含一个测试用例,第1行输入 N ( 1 ≤ N ≤ 100 ) N(1≤N≤100) N(1≤N≤100)和 M ( ≥ 0 ) M(≥0) M(≥0);第2行输入 N N N个整数,之间用空格分隔。
输出格式:
在一行中输出循环右移 M M M位以后的整数序列,之间用空格分隔,序列结尾不能有多余空格。
输入样例:
6 2
1 2 3 4 5 6
输出样例:
5 6 1 2 3 4
思路1(2020-4-10 14:44:49)
你说不用多余数组我就不用?那我不是很没面子?
我要是用了然后你卡我内存那我就更没面子了。。。
不用就不用,谁爱用谁用。反正你不检查我代码,我这样搞,你有脾气吼~
这个答案实在是,阴险狡诈。
答案1(2020-4-10 13:34:49)
#include <iostream>
using namespace std;
int main(int argc, char** argv) {
int n;
int moveL;
cin >> n;
cin >> moveL;
int arr[n];
for(int i = 0 ; i < n; i++)
cin >> arr[i];
// I don't like move even once,output directly
for(int i = n - (moveL % n) ; i < n ; i++) // if int i = n - moveL then 2 test point fail
cout << arr[i] << " ";
cout << arr[0] ;
for(int i = 1 ; i < n - (moveL % n); i++)
cout << " " << arr[i] ;
return 0;
}
思路2(2020-4-10 15:11:21)
既然是学习,就不要太,投机取巧了。
乖乖做题。
思路是,从第一个数往后挪,被挪到的也依次往后挪,直到挪到重合原来的位置,再接着挪下一个。或者挪到挪动次数等于数组大小,就不挪了。
例子1:
- 输入 1 , 2 , 3 , 4 , 5 , 6 1,2,3,4,5,6 1,2,3,4,5,6 往右挪2个位置,
- 从第1个位置的数开始,把第1个位置的数挪到第3个位置,第3个位置的数先找个地方放着,结果是
1 , 2 , 1 , 4 , 5 , 6 , ( t e m p = 3 ) 1,2,1,4,5,6, (temp =3) 1,2,1,4,5,6,(temp=3) - 然后再安排原来第3个位置的数,把第3个位置的数挪到第5个位置,第5个位置的数先找个地方放着,结果是
1 , 2 , 1 , 4 , 3 , 6 , ( t e m p = 5 ) 1,2,1,4,3,6,(temp=5) 1,2,1,4,3,6,(temp=5) - 然后再安排原来第5个位置的数,把第5个位置的数挪到第1个位置,和起点重复,直接挪进去结果是
5 , 2 , 1 , 4 , 3 , 6 5,2,1,4,3,6 5,2,1,4,3,6 - 接着挪下一个,从第2个位置的数开始,把第2个位置的数挪到第4个位置,第4个位置的数先找个地方放着,结果是
5 , 2 , 1 , 2 , 3 , 6 ( t e m p = 4 ) 5,2,1,2,3,6 (temp =4) 5,2,1,2,3,6(temp=4) - 然后再安排原来第4个位置的数,把第4个位置的数挪到第6个位置,第6个位置的数先找个地方放着,结果是
5 , 2 , 1 , 2 , 3 , 4 ( t e m p = 6 ) 5,2,1,2,3,4 (temp =6) 5,2,1,2,3,4(temp=6) - 然后再安排原来第6个位置的数,把第6个位置的数挪到第2个位置,和起点重复,直接挪进去结果是
5 , 6 , 1 , 2 , 3 , 4 5,6,1,2,3,4 5,6,1,2,3,4 - 总共挪了6次了,移动结束,输出。
例子2:
- 输入 1 , 2 , 3 , 4 , 5 , 6 , 7 1,2,3,4,5,6,7 1,2,3,4,5,6,7 往右挪4个位置,
- 从第1个位置的数开始,把第1个位置的数挪到第5个位置,第5个位置的数先找个地方放着,结果是
1 , 2 , 3 , 4 , 1 , 6 , 7 , ( t e m p = 5 ) 1,2,3,4,1,6,7, (temp =5) 1,2,3,4,1,6,7,(temp=5) - 然后再安排原来第5个位置的数,把第5个位置的数挪到第2个位置,第2个位置的数先找个地方放着,结果是
1 , 5 , 3 , 4 , 1 , 6 , 7 , ( t e m p = 2 ) 1,5,3,4,1,6,7,(temp=2) 1,5,3,4,1,6,7,(temp=2) - 然后再安排原来第2个位置的数,把第2个位置的数挪到第6个位置,第6个位置的数先找个地方放着,结果是
1 , 5 , 3 , 4 , 1 , 2 , 7 , ( t e m p = 6 ) 1,5,3,4,1,2,7,(temp=6) 1,5,3,4,1,2,7,(temp=6) - 然后再安排原来第6个位置的数,把第6个位置的数挪到第3个位置,第3个位置的数先找个地方放着,结果是
1 , 5 , 6 , 4 , 1 , 2 , 7 ( t e m p = 3 ) 1,5,6,4,1,2,7 (temp =3) 1,5,6,4,1,2,7(temp=3) - 然后再安排原来第3个位置的数,把第3个位置的数挪到第7个位置,第7个位置的数先找个地方放着,结果是
1 , 5 , 6 , 4 , 1 , 2 , 3 ( t e m p = 7 ) 1,5,6,4,1,2,3 (temp =7) 1,5,6,4,1,2,3(temp=7) - 然后再安排原来第7个位置的数,把第7个位置的数挪到第4个位置,第4个位置的数先找个地方放着,结果是
1 , 5 , 6 , 7 , 1 , 2 , 3 ( t e m p = 4 ) 1,5,6,7,1,2,3 (temp =4) 1,5,6,7,1,2,3(temp=4) - 然后再安排原来第4个位置的数,把第4个位置的数挪到第1个位置,和起点重复,直接挪进去结果是
4 , 5 , 6 , 7 , 1 , 2 , 3 4,5,6,7,1,2,3 4,5,6,7,1,2,3 - 总共挪了7次了,移动结束,输出。
答案2 (2020-4-10 14:29:09)
#include <iostream>
using namespace std;
int main(int argc, char** argv) {
int n;
int moveL;
cin >> n;
cin >> moveL;
int arr[n];
for(int i = 0 ; i < n; i++)
cin >> arr[i];
int changetimes = 0;
//moving
for(int i = 0 ; i < (moveL % n) ; i++)
{
if(changetimes >= n)
break;
int step = ( moveL % n );
int toBeChangeIndex = (i + step) % n ;
int temp = arr[i];
int temp2;
while(toBeChangeIndex != i){
//swap arr[toBeChangeIndex] with temp
temp2 = arr[toBeChangeIndex];
arr[toBeChangeIndex]= temp;
temp = temp2;
changetimes ++;
toBeChangeIndex = (toBeChangeIndex + step) %n ;
}
arr[i] = temp;
changetimes ++;
}
cout << arr[0];
for(int j = 1 ; j < n; j++)
cout << " " << arr[j] ;
return 0;
}
思路3 (2020-4-10 15:22:11)
写完博客信心满满去百度看其他dalao,我就又泪流满面的回来了。
其实就是要把一个数组1234abcd,给变成abcd1234,假如把前边当成一个整体a,把后边当成一个整体A,就是要把aA翻成Aa,但是直接翻1234abcd会变成dcba4321,a和A内部颠倒了,那就再把内部也翻一下就好了。
这个思路之前复习的时候有看到过,我怎么就给忘了呢,辛辛苦苦敲了半天的码和博客,一文不值,emmmmm。
答案3(2020-4-10 15:46:27)
无敌一般的存在,给我学!
#include <iostream>
using namespace std;
//reverse array arr between index a and b ,include swap a,b
//a<b
void reverse(int arr[], int a , int b)
{
int temp;
int j = b;
for(int i = a; i < (b - a + 1) / 2 + a ; i++)
{
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
j--;
}
}
int main(int argc, char** argv) {
int n,moveL;
cin >> n >> moveL;
int arr[n];
for(int i = 0 ; i < n ; i++)
cin >> arr[i];
moveL = moveL % n;
reverse(arr,0,n-1);
reverse(arr , 0 , moveL - 1);
reverse(arr , moveL,n-1);
cout << arr[0];
for(int i = 1 ; i < n ; i++)
cout << " " << arr[i] ;
cout << endl;
return 0;
}