设将 n(n>1) 个整数存放到一维数组 R 中。设计一个在时间和空间两方面都尽可能高效的算法。将 R 中保存的序列循环左移 p(0<p<n) 个位置,即将 R 中的数据由 (X0,X1,...,Xn−1) 变换为 (Xp,Xp+1,...,Xn−1,X0,X1,...,Xp−1)。
// 辅助函数:将数组 R 中从下标 from 到 to 的元素逆置 voidReverse(int R[], int from, int to) { int i, temp; // 使用双指针,i指向头,to指向尾,向中间靠拢并交换 for (i = 0; i < (to - from + 1) / 2; i++) { temp = R[from + i]; R[from + i] = R[to - i]; R[to - i] = temp; } }
// 主函数:将数组 R 循环左移 p 个位置 voidCycleLeftMove(int R[], int n, int p) { // 如果 p 非法或无需移动,直接返回 if (p <= 0 || p >= n) return;
// 1. 逆置前 p 个元素 [0, p-1] Reverse(R, 0, p - 1); // 2. 逆置剩余 n-p 个元素 [p, n-1] Reverse(R, p, n - 1); // 3. 逆置整个数组 [0, n-1] Reverse(R, 0, n - 1); }
// 测试代码 intmain() { int R[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; int n = 10; int p = 3; // 循环左移3位
CycleLeftMove(R, n, p);
printf("Result: "); for (int i = 0; i < n; i++) { printf("%d ", R[i]); } // 预期输出: 3 4 5 6 7 8 9 0 1 2 return0; }
4. 复杂度分析
时间复杂度:
该算法主要由三次逆置操作组成。
第一次逆置涉及 p 个元素,操作次数约为 p/2。
第二次逆置涉及 n−p 个元素,操作次数约为 (n−p)/2。
第三次逆置涉及 n 个元素,操作次数约为 n/2。
总的操作次数为 2n 次扫描。
因此,时间复杂度为 O(n)。
空间复杂度:
算法是在原数组上进行操作(In-place),只需要用到有限的几个辅助变量(如 i, temp, from, to)来进行交换和循环控制,不需要额外的数组空间。
因此,空间复杂度为 O(1)。