有 个整数,使其前面各数顺序向后移 个位置,最后 个数变成最前面的 个数。
例如:数组 向后移 位,结果应为。
本题要求实现数组的循环右移(也称“旋转”)操作。关键在于理解“向后移 个位置”的含义:
原数组中最后 个元素移到最前面;
剩下的前 个元素整体向后平移 位。
这实际上是将数组分为两部分:
后段:
前段:
然后将后段拼接到前段之前,形成新数组。
注意:若,应取,避免无效移动(如移 位等于没动)。题目示例未处理此情况,但实际应用中建议加上。
输入数字个数n:
5
输入后移位数m:
2
请输入第1个数: 1
请输入第2个数: 2
请输入第3个数: 3
请输入第4个数: 4
请输入第5个数: 5原数据排序为:
1 2 3 4 5
移动后排序为;
4 5 1 2 3 设原数组为,目标是得到新数组,满足:
等价于:
即切片拼接操作。
此操作在计算机科学中称为 “数组旋转”,常见于缓存管理、密码学、图像处理等领域。高效实现方式包括:
使用额外空间(如本题两种方法)
原地旋转(三次反转法,空间复杂度)
使用 LinkedList 和子列表(SubList)
import java.util.LinkedList;
import java.util.List;
import java.util.Scanner;
public class Demo {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.println("输入数字个数n:");
int n = in.nextInt();
System.out.println("输入后移位数m:");
int m = in.nextInt();
// 处理 m >= n 的情况(健壮性增强)
m = m % n;
if (m == 0) {
System.out.println("无需移动");
return;
}
LinkedList<Integer> list = new LinkedList<>();
for (int i = 0; i < n; i++) {
System.out.println("请输入第" + (i + 1) + "个数:");
list.add(in.nextInt());
}
System.out.println("原数据排序为:");
for (int t : list) {
System.out.print(t + " ");
}
System.out.println();
// 切分:后 m 个 + 前 n-m 个
List<Integer> lastM = list.subList(list.size() - m, list.size());
List<Integer> firstPart = list.subList(0, list.size() - m);
// 将后 m 个插入到前段开头
firstPart.addAll(0, lastM);
System.out.println("移动后排序为:");
for (int t : firstPart) {
System.out.print(t + " ");
}
}
}注意:
subList返回的是原列表的视图,直接修改会影响原列表。此处通过addAll(0, ...)修改firstPart(即原list的前段),从而改变整个list。
使用辅助数组(更清晰)
import java.util.Scanner;
public class Demo {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.println("请定义数组的长度:");
int n = in.nextInt();
System.out.println("请输入移动的位数:");
int m = in.nextInt();
// 增强健壮性
m = m % n;
if (m == 0) {
System.out.println("无需移动");
return;
}
int[] arr = new int[n];
int[] temp = new int[m]; // 临时保存最后 m 个数
// 输入
for (int i = 0; i < n; i++) {
System.out.println("请输入第" + (i + 1) + "个数:");
arr[i] = in.nextInt();
}
System.out.println("排序前:");
for (int x : arr) System.out.print(x + " ");
System.out.println();
// 1. 保存最后 m 个数到 temp
for (int i = 0; i < m; i++) {
temp[i] = arr[n - m + i];
}
// 2. 将前 n-m 个数向后移动 m 位(从后往前避免覆盖)
for (int i = n - m - 1; i >= 0; i--) {
arr[i + m] = arr[i];
}
// 3. 将 temp 中的数放到最前面
for (int i = 0; i < m; i++) {
arr[i] = temp[i];
}
System.out.println("排序后:");
for (int x : arr) System.out.print(x + " ");
}
}经典算法:该问题也可用 三次反转法 实现原地旋转(不使用额外数组):
reverse(arr, 0, n-1);
reverse(arr, 0, m-1);
reverse(arr, m, n-1);时间复杂度,空间复杂度。
应用场景:循环缓冲区、字符串旋转、加密算法中的位移操作等。
此题是理解数组切片、索引映射和内存操作的重要练习,也是面试常见题型。