配列の逆順の基本アイデア
はじめは少し戸惑うかもしれないけど、やることはシンプルです。配列の「最初」と「最後」を入れ替え、次に「2番目」と「最後から2番目」を入れ替える——これを中央に向かって繰り返すだけで、逆順になります。
手順をかみ砕いて説明
- 両端から内側へ動かす:
- 左からの位置を表す変数を用意します(例:
f)。 - 右からの位置を表す変数も用意します(例:
l)。 fは 0 から右へ進み、lは 配列の長さ-1 から左へ進みます。
- 左からの位置を表す変数を用意します(例:
- 入れ替えのやり方:
- いきなり上書きすると値が消えるので、一時変数(例:
temp)にどちらかを退避してから入れ替えます。
- いきなり上書きすると値が消えるので、一時変数(例:
- いつ止めるか:
fがlより小さい間だけ入れ替えます。- 偶数要素なら中央ですれ違い、奇数要素なら中央の要素は触らずそのままになります。
例題1:整数配列を逆順にする(基本)
import java.util.Arrays;
public class ReverseArrayBasic {
public static void main(String[] args) {
int[] src = {12, 24, 18, 31, 17};
System.out.println("Before: " + Arrays.toString(src)); // [12, 24, 18, 31, 17]
// 両端から入れ替える
for (int f = 0, l = src.length - 1; f < l; f++, l--) {
int temp = src[f]; // 退避
src[f] = src[l]; // 右端を左へ
src[l] = temp; // 退避していた左端を右へ
}
System.out.println("After : " + Arrays.toString(src)); // [17, 31, 18, 24, 12]
}
}
Java- ポイント:
f < lが止め時。中央に到達したら終わり。tempは値を失わないための「避難所」。f++とl--で、左と右から一歩ずつ近づきます。
例題2:文字列配列も同じ手順でOK
import java.util.Arrays;
public class ReverseStringArray {
public static void main(String[] args) {
String[] names = {"Taro", "Hanako", "Ken", "Ami"};
System.out.println("Before: " + Arrays.toString(names)); // [Taro, Hanako, Ken, Ami]
for (int f = 0, l = names.length - 1; f < l; f++, l--) {
String temp = names[f];
names[f] = names[l];
names[l] = temp;
}
System.out.println("After : " + Arrays.toString(names)); // [Ami, Ken, Hanako, Taro]
}
}
Java- ポイント:
- 型が
Stringでも考え方は同じ。 - 参照型でも「退避→入れ替え」の流れは同じです。
- 型が
別パターン:元の配列を変えずに「逆順のコピー」を作る
import java.util.Arrays;
public class ReverseToNewArray {
public static void main(String[] args) {
int[] src = {10, 20, 30, 40, 50};
int[] dest = new int[src.length];
// 左から右へ読みつつ、右から左へ書く
for (int i = 0; i < src.length; i++) {
dest[src.length - 1 - i] = src[i];
}
System.out.println("src : " + Arrays.toString(src)); // [10, 20, 30, 40, 50]
System.out.println("dest: " + Arrays.toString(dest)); // [50, 40, 30, 20, 10]
}
}
Java- ポイント:
dest[length - 1 - i]が「逆側の位置」。- 元の配列を壊したくないときに便利。
つまずきポイントと直し方
- インデックスの範囲外エラー:
- 原因:
lの初期値をlengthにしてしまう。 - 対策: 右端は常に
length - 1。
- 原因:
- 上書きで値が消える:
- 原因: 退避せずに代入を連続で行う。
- 対策: 必ず 一時変数
tempを使う。
- ループが止まらない/止まるのが早い:
- 原因: 条件を
f <= lにして中央で二度入れ替えしてしまうか、逆にf > lを使ってしまう。 - 対策: 条件は
f < lが安全。
- 原因: 条件を
- 奇数/偶数の中央の扱い:
- 理解: 奇数長は中央の要素は動かさない、偶数長は中央で入れ替えが終わる。
練習課題(手を動かして慣れる)
- 偶数長の配列で検証:
- 例:
{1, 2, 3, 4, 5, 6}を逆順に。 - 途中で
fとlの値をSystem.out.printlnで出して、動きを追ってみる。
- 例:
- 配列が空/1要素の場合:
- 例:
{}や{42}でもコードが落ちないか確認。 - 期待結果は「そのまま」。
- 例:
- メソッドにする:
static void reverse(int[] a)を作って、どの配列にも使えるようにする。- 参照渡しなので、呼び出し元の配列が直接入れ替わることも確認。
public static void reverse(int[] a) {
for (int f = 0, l = a.length - 1; f < l; f++, l--) {
int temp = a[f];
a[f] = a[l];
a[l] = temp;
}
}
Java補足:配列以外(リスト)なら簡単に逆順
- Javaのリストなら:
Collections.reverse(list);で一発逆順。- ただし、今回学んだ「入れ替えの仕組み」はアルゴリズムの基本なので、配列で手作りする経験が大事。
