习题8-3 数组循环右移 (20 分)
时间: 2023-05-31 09:01:53 浏览: 210
### 回答1:
题目描述
给定一个长度不超过 10^5的正整数数组a,以及一个正整数m。请你编写一个数组循环右移的程序,即把数组a中的元素向右移动m个位置,其中最后m个元素移到最前面,其余元素向后移动m个位置。
输入格式:
第一行包含两个正整数n和m,表示数组a的长度以及右移长度。
第二行包含n个正整数,表示数组a中的元素。
输出格式:
共一行,包含n个正整数,表示移动后的数组。
输入样例:
6 2
1 2 3 4 5 6
输出样例:
5 6 1 2 3 4
算法1
(暴力枚举) $O(n^2)$
先将前n-m个数倒序,再将后m个数倒序,最后将整个数组倒序即可。
时间复杂度
参考文献
python3 代码
C++ 代码
算法2
(暴力枚举) $O(n^2)$
blablabla
时间复杂度
参考文献
C++ 代码
### 回答2:
本题要求将一个数组循环右移。循环右移指的是将数组的元素从右边开始向左移动若干个位置后,最后将被“挤出去”的部分通过数组的左边重新进入数组的右边,形成一个循环的效果。
代码如下:
```c++
#include <iostream>
using namespace std;
int main() {
int n, m; // n表示数组长度,m表示移动的位数
cin >> n >> m;
int a[n]; // 定义数组
for (int i = 0; i < n; i++) {
cin >> a[i]; // 输入数组元素
}
m = m % n; // 如果m>n,那么右移m个位置与右移m%n个位置是等价的
// 把移动的m个元素保存到一个临时数组中
int temp[m];
for (int i = n - m; i < n; i++) {
temp[i - n + m] = a[i];
}
// 移动数组a中的n-m个元素
for (int i = n - m - 1; i >= 0; i--) {
a[i + m] = a[i];
}
// 把临时数组中的m个元素放回数组a的前m个位置
for (int i = 0; i < m; i++) {
a[i] = temp[i];
}
// 输出移动后的数组元素
for (int i = 0; i < n; i++) {
if (i != 0) {
cout << " ";
}
cout << a[i];
}
return 0;
}
```
首先我们需要输入数组的长度$n$和移动的位数$m$,然后定义一个长度为$n$的数组$a$,依次读入$n$个整数作为数组元素。如果$m>n$,那么右移$m$个位置与右移$m\%n$个位置是等价的。
接下来,我们把移动的$m$个元素保存到一个临时数组$temp$中,假设数组$a$长度为$n$,要把它向右移动$m$个位置,那么需要把$a_{n-m}$到$a_{n-1}$这$m$个元素保存到$temp$数组中。其中$a_{i-n+m}$表示把$a_i$移动$m$个位置以后,它在数组$a$中的最终位置,$i-n+m$的含义就是把它调整到$temp$数组对应的位置上。
接下来,我们需要把数组$a$中的$n-m$个元素向右移动$m$个位置。为了避免数据覆盖,我们需要从$a_{n-m-1}$开始遍历数组,逐个把元素移动到$a_{i+m}$的位置上。这里需要注意,我们是从数组的后面开始遍历的,因为如果从前往后遍历,被移动的元素就会覆盖还未被移动的元素。
最后,我们需要把临时数组$temp$中的$m$个元素放回数组$a$的前$m$个位置,也就是把$temp_{0}$到$temp_{m-1}$这$m$个元素依次赋值给$a_{0}$到$a_{m-1}$。
最后,我们依次输出移动后的数组元素。输出时需要注意,每个元素后面都要跟一个空格,最后一个元素后面不需要跟空格。因此,我们需要在输出每个元素之前判断一下是否需要输出空格。
综上所述,本题需要我们掌握如何对数组进行循环位移,要注意数组的下标取值和保存临时变量的数量。
### 回答3:
本题题目要求我们对一个长度为N的数组进行循环右移k位的操作,最后输出结果数组。
首先,我们可以分析出,对于一个长度为N的数组A,循环右移k位可以看作将数组A分为两段,前N-k个元素和后k个元素,交换两段元素的顺序,即前k个元素放到数组末尾去。那么我们可以写出下面的代码:
```
#include <stdio.h>
void reverse(int arr[], int L, int R){
while(L < R){
int temp = arr[L];
arr[L] = arr[R];
arr[R] = temp;
L++;
R--;
}
}
int main(){
int n, k;
scanf("%d %d", &n, &k);
int arr[105];
for(int i = 0; i < n; i++){
scanf("%d", &arr[i]);
}
// 将前N-k个元素翻转
reverse(arr, 0, n-k-1);
// 将后k个元素翻转
reverse(arr, n-k, n-1);
// 翻转整个数组
reverse(arr, 0, n-1);
// 输出数组
for(int i = 0; i < n; i++){
printf("%d ", arr[i]);
}
return 0;
}
```
我们先定义了一个reverse函数,用于翻转数组中的一段元素。在主函数中,我们先输入数组的长度n和循环右移的位数k,然后输入n个数组元素。接下来,我们将前N-k个元素翻转,再将后k个元素翻转,最后再将整个数组翻转,就得到了循环右移k位后的结果数组了。输出数组即可。
需要注意的是,当循环右移的位数k大于数组的长度n时,相当于循环右移k%n位。因此这种情况下,我们只需要将k取模即可,实现代码如下:
```
if(k > n){
k = k % n;
}
```
至此,我们完成了这道题目的解答。这种问题是比较基础的算法问题,但是如果没有掌握翻转数组元素的技巧,代码可能会比较难写。因此我们在平时的学习中,应该注重这些基础算法的学习和掌握,这样才能更好地解决复杂的问题。
阅读全文