三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

题解:学而思编程 数组旋转

题解:学而思编程 数组旋转

【题目来源】

学而思编程:数组旋转

【题目描述】

给定一个整数数组 \(a_1,a_2,⋯ ,a_n\),然后输入一系列数字 \(x_1,x_2,⋯ ,x_m\),如果 \(x_i>0\),代表将数组中的元素向右旋转 \(x_i\) 个位置(例如,\(1,2,3,4,5\) 向右旋转 \(2\) 个位置将变成 \(4,5,1,2,3\))。如果 \(x_i<0\),代表将数组中的元素向左旋转 \(−x_i\) 个位置(例如,\(x_i=−3\) 时,\(1,2,3,4,5\) 向左旋转 \(3\) 个位置将变成 \(4,5,1,2,3\))。

【输入】

输入第一行一个整数 \(n\),表示数组的元素个数。

第二行 \(n\) 个空格分隔的整数,表示数组 \(a_i\)

第三行一个整数 \(m\),表示旋转次数。

第二行 \(m\) 个空格分隔的整数,表示每次旋转的位置\(x_i\)

【输出】

输出 \(m\) 行,第 \(i\) 行输出 \(n\) 个空格分隔的整数,表示第 \(i\) 次旋转后的数组情况。

【输入样例】

7
1 3 5 7 2 4 6
5
0 1 -2 3 -4

【输出样例】

1 3 5 7 2 4 6
6 1 3 5 7 2 4
3 5 7 2 4 6 1
4 6 1 3 5 7 2
5 7 2 4 6 1 3

【核心思想】

  1. 问题描述:给定长度为 \(n\) 的数组 \(a\),执行 \(m\) 次旋转操作(\(x_i > 0\) 向右旋转 \(x_i\) 位,\(x_i < 0\) 向左旋转 \(-x_i\) 位),每次操作后输出当前数组。这是一个模拟问题,核心在于用偏移量避免实际移动数组元素,\(O(1)\) 完成每次旋转。

  2. 算法选择

    • 偏移量追踪:维护一个偏移量 \(p\),表示数组逻辑上的起始位置相对于物理存储的偏移
    • 模运算:所有操作转化为偏移量的加减,对 \(n\) 取模
  3. 关键步骤

    • 初始化:读取 \(n\)、数组 \(a[0..n-1]\)\(m\)
    • 偏移量初始化\(p = 0\)(逻辑起始位置为物理位置 \(0\)
    • 处理每次旋转\(m\) 次):
      • 读取 \(x\)
      • 更新偏移量\(p -= x\)(向右旋转 \(x\) 位等价于逻辑起始位置左移 \(x\) 位,即 \(p\)\(x\)
      • 取模规范化\(p = p \% n\)(控制偏移量在 \([-n+1, n-1]\) 范围内)
      • 输出数组:遍历 \(i = 0\)\(n-1\),输出 \(a[(i + p + n) \% n]\)\(+n\) 再取模处理负数)
    • 注意:向右旋转 \(x\) 位(如 \(1,2,3,4,5 \to 4,5,1,2,3\))等价于逻辑起始位置从 \(0\) 变为 \(n-x\),即 \(p = -x\)
  4. 时间/空间复杂度

    • 时间复杂度:\(O(n \times m)\),每次输出 \(n\) 个元素
    • 空间复杂度:\(O(n)\),原数组存储
  5. 模拟的核心思想

    • 虚拟索引:不实际移动数组元素,而是通过偏移量计算逻辑位置到物理位置的映射
    • 模运算优雅处理环形\(p\) 的更新和查询都通过对 \(n\) 取模实现,天然支持左右旋转的统一处理
    • 负数处理\(+n\) 后再取模确保索引始终非负
    • 适用于数组旋转、环形缓冲区、循环队列类问题

【算法标签】

模拟

【代码详解】

#include <bits/stdc++.h>
using namespace std;
const int N = 1005;
int a[N];  // 存储数组
int n, m;  // n: 数组长度,m: 操作次数
int main()
{cin >> n;  // 输入数组长度for (int i = 0; i < n; i++)  // 输入数组元素cin >> a[i];cin >> m;  // 输入操作次数int p = 0;  // 偏移量,表示当前数组相对于原始数组的偏移while (m--)  // 处理每次操作{int x;  // 操作数cin >> x;  // 输入操作数p -= x;  // 更新偏移量p %= n;  // 取模,防止偏移量过大for (int i = 0; i < n; i++)  // 输出数组cout << a[(i + p + n) % n] << " ";  // 通过偏移量计算实际位置cout << endl;  // 换行}return 0;
}

【运行结果】

7
1 3 5 7 2 4 6
5
0 1 -2 3 -4
1 3 5 7 2 4 6
6 1 3 5 7 2 4
3 5 7 2 4 6 1
4 6 1 3 5 7 2
5 7 2 4 6 1 3
← 返回列表