有 n 個整數(0 < n ≤ 20),將其順序向後移動 m 位置(m < n),最後 m 個數移到最前面。
範例:
輸入:8 3 1 2 3 4 5 6 7 8 輸出:6 7 8 1 2 3 4 5
原代碼存在多處嚴重邏輯錯誤:
scanf("%d", a) 缺少 & 且僅讀取單一整數,非陣列a[n-i]、a[j] 邏輯混亂,會越界if(n20) 缺少運算子,應為 if(n > 20)將陣列視為兩段:[0, n-m-1] 和 [n-m, n-1]。目標交換兩段順序。
reverse(0, n-1)reverse(0, m-1)reverse(m, n-1)範例演示: 1 2 3 4 5 6 7 8, m=3
整體反轉:8 7 6 5 4 3 2 1 反轉前3:6 7 8 5 4 3 2 1 反轉後5:6 7 8 1 2 3 4 5 ✓
#include <stdio.h>
void reverse(int arr[], int left, int right) {
while (left < right) {
int temp = arr[left];
arr[left] = arr[right];
arr[right] = temp;
left++;
right--;
}
}
int main() {
int n, m;
int a[20];
printf("輸入總數 n (1-20): ");
scanf("%d", &n);
if (n < 1 || n > 20) { printf("錯誤:n 超出範圍\n"); return 1; }
printf("輸入後移位數 m (0-%d): ", n-1);
scanf("%d", &m);
if (m < 0 || m >= n) { printf("錯誤:m 超出範圍\n"); return 1; }
printf("輸入 %d 個整數: ", n);
for (int i = 0; i < n; i++) {
scanf("%d", &a[i]);
}
// 三步反轉法
reverse(a, 0, n - 1);
reverse(a, 0, m - 1);
reverse(a, m, n - 1);
printf("移動後的數列: ");
for (int i = 0; i < n; i++) {
printf("%d ", a[i]);
}
printf("\n");
return 0;
}
int b[20];
for (int i = 0; i < n; i++) {
b[(i + m) % n] = a[i]; // 計算新位置
}
// 複製回 a 或直接輸出 b
| 輸入 | 預期輸出 | 說明 |
|---|---|---|
| 5 0 1 2 3 4 5 | 1 2 3 4 5 | m=0 不移動 |
| 5 4 1 2 3 4 5 | 2 3 4 5 1 | m=n-1 最大移動 |
| 1 0 99 | 99 | 單元素邊界 |
陣列循環移位是經典演算法題。三步反轉法空間效率最佳,適合嵌入式/面試場合;額外陣列法直觀易寫,適合一般應用。關鍵在於:正確讀取輸入、邊界檢查、索引計算無誤。建議新手先掌握額外陣列法理解核心邏輯,再學習原地反轉優化。