こんにちは!
学校のJavaの例題で、四つの重複しないマークの順列を全て書き出す
メソッドを作るっていう問題が出ました!
ネットを見ながらで、何とか再起を使って吐き出すのは組めたんですけど、
先生に見せたら、『まだ再起は教えていない』って言われて、合っているのに
NGを食いました><
どうやら、for文の入れ子と配列の要素の入れ替えだけでできるらしいんですが、
どうやって書けばいいのかが解りません…。
パターンの数を出すのは解るんです。4*3*2ですしね。でも、再起を
使っている例をとっても、どうしてこのソースですべての順列が出せるのか、
その仕組みが解りません。
ソースだけじゃなくて、どうして全部の順列が出せるのか、その仕組みも併せて
教えてください!!
中身は、こんな感じです。
// 順列を出す配列
private int[] arr={0,1,2,3};
private void permutation(int n)
{
if (n < 4)
{
// n以上4未満
for (int i = n; i < 4; i++)
{
if (n != i)
{
this.swap(n, i);
}
// 再起呼び出し
permutation(n + 1);
if (n != i)
{
this.swap(n, i);
}
}
}
else
{
System.out.println(this.arr[0] + "," + this.arr[1] + "," + this.arr[2] + "," + this.arr[3]);
}
}
private void swap(int a,int b)
{
int c = this.arr[a];
this.arr[a] = this.arr[b];
this.arr[b] = c;
}
何もわからなくてゴメンナサイ。
よろしくお願いします^^
A 回答 (4件)
- 最新から表示
- 回答順に表示
No.4
- 回答日時:
以下のようにしてください。
------------------------------------------------
// 順列を出す配列
private char[] arr={'A','B','C','D'};
private void permutation(int n)
{
for (int i = 0; i < 4; i++)
{
if (i != 0)
{
this.swap(0,i);
}
for (int j = 1; j < 4; j++)
{
if (j != 1)
{
this.swap(1,j);
}
for (int k = 2; k < 4; k++)
{
if (k != 2)
{
this.swap(2,k);
}
System.out.println(this.arr[0] + "," + this.arr[1] + "," + this.arr[2] + "," + this.arr[3]);
if (k != 2)
{
this.swap(2,k);
}
}
if (j != 1)
{
this.swap(1,j);
}
}
if (i != 0)
{
this.swap(0,i);
}
}
}
private void swap(int a,int b)
{
char c = this.arr[a];
this.arr[a] = this.arr[b];
this.arr[b] = c;
}
---------------------------------------------------------------
これは、再帰を使用しない方法です。
以下、実行結果です。
A,B,C,D
A,B,D,C
A,C,B,D
A,C,D,B
A,D,C,B
A,D,B,C
B,A,C,D
B,A,D,C
B,C,A,D
B,C,D,A
B,D,C,A
B,D,A,C
C,B,A,D
C,B,D,A
C,A,B,D
C,A,D,B
C,D,A,B
C,D,B,A
D,B,C,A
D,B,A,C
D,C,B,A
D,C,A,B
D,A,C,B
D,A,B,C
今回、判り易くするために、A,B,C,Dの文字を使用していますが、0,1,2,3を
使いたいのであれば、
private char[] arr={'A','B','C','D'}; を
private int[] arr={0,1,2,3}; に戻します。
更に void swapメソッド中の
char c = this.arr[a]; を
int c = this.arr[a]; に戻します。
そうすれば、あなたが提示したソースと同じ結果が得られます。
それで、何故、上記の結果が得られるかということですが、以下のようになります。
1.A,B,C,Dの文字を出力するとき、1番目の文字を選ぶ。
これは、for(int i=0;i < 4;i++)のループです。
これは、i=0の場合は、そのままで良いが、以外の場合は、最初の文字とその処理中の文字を入れ変える必要があります。
つまり、Bの文字を処理するときは、A,B,C,DをB,A,C,Dのように置き換えます。
同様に、Cの文字を処理するときは、A,B,C,DをC,B,A,Dのように置き換えます。
同様に、Dの文字を処理するときは、A,B,C,DをD,B,C,Aのように置き換えます。
そして、ループの最後で、置き換えた文字を元に戻しておきます。
2.A,B,C,Dの文字を出力するとき、2番目の文字を選ぶ。
これは、for(int j=0;j < 4;j++)のループです。
これは、j=1の場合は、そのままで良いが、以外の場合は、2番目の文字とその処理中の文字を入れ変える必要があります。
つまり、Cの文字を処理するときは、A,B,C,DをA,C,B,Dのように置き換えます。
同様に、Dの文字を処理するときは、A,B,C,DをA,D,C,Bのように置き換えます。
そして、ループの最後で、置き換えた文字を元に戻しておきます。
3.A,B,C,Dの文字を出力するとき、3番目の文字を選ぶ。
これは、for(int k=2;k < 4;j++)のループです。
これは、k=2の場合は、そのままで良いが、以外の場合は、3番目の文字とその処理中の文字を入れ変える必要があります。
つまり、Dの文字を処理するときは、A,B,C,DをA,B,D,Cのように置き換えます。
そして、ループの最後で、置き換えた文字を元に戻しておきます。
4.ここは、arrの並べ替えた文字を印字する箇所です。
System.out.println(・・・省略・・・)
不明点があれば、補足してください。
ありがとうございます!
少しわかりました!
つまり、一つのループごとにループの初めの数とループしている数を入れ替える
わけですね!
入れ替えというから、二重にループさせてそのiとjを入れ替えるのだとばかり
思っていました!
あと、どうして入れ替えた後で一度戻しているのか、
勿論、一つ一つ指でなぞりながらでもおっていけばその通りには
なるんですけど、なんか戻していたら、一行おきにもとの並び方に
戻ってしまいそうな気がします。
なので、コードはやってることは解るんですけど、『良くバラバラに
順列ができるなぁ』と思ってしまうわけです。
いくらサンプル通りに組んでうまくいっても、『どうしてそうなるのか』が
解らないと気持ち悪いですよね。
ありがとうございました!いただいたコードをもとに、もう一度試してみます!
No.3
- 回答日時:
> 解らない人に教えるわけですから、自分が解っているからって
> いい加減な回答はしないでくださいね^^
再帰をご理解いただいているようなのでご理解いただけると判断したのですが
質問者様の理解力を見誤ったようで失礼しました。
閑話休題
要素が数字だと紛らわしいので文字にします。
arr={"A","B","C","D"};
4重ループで得られた数字が、外側のループから順に2,3,1,0だとすると
この要素番号で順にaryから要素を取り出して順に並べます。
arr1[0] = arr[2];
arr1[1] = arr[3];
arr1[2] = arr[1];
arr1[3] = arr[0];
結果としてarr1 = {"C","D","B","A"}になります。
これを4重ループで得られる重複しない組み合わせで実行すれば良いわけです。
これでご理解いただけましたでしょうか?
…多分、私と同じ人もこれを見ただけじゃ解らないと思いますよ。
>4重ループで得られた数字が、外側のループから順に2,3,1,0だとすると
>この要素番号で順にaryから要素を取り出して順に並べます。
これだと、実際に『入れ替え』をやっていないし。
ソースにもswapって書いてあるわけですし、自分勝手な解釈で答えられても…
ねぇ?って思います。
siffon9さんは、多分『人に何かを教える』のは苦手なのではないでしょうか。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・【大喜利】【投稿~11/12】 急に朝起こしてきた母親に言われた一言とは?
- ・好きな和訳タイトルを教えてください
- ・うちのカレーにはこれが入ってる!って食材ありますか?
- ・好きな「お肉」は?
- ・あなたは何にトキメキますか?
- ・おすすめのモーニング・朝食メニューを教えて!
- ・「覚え間違い」を教えてください!
- ・とっておきの手土産を教えて
- ・「平成」を感じるもの
- ・秘密基地、どこに作った?
- ・【お題】NEW演歌
- ・カンパ〜イ!←最初の1杯目、なに頼む?
- ・一回も披露したことのない豆知識
- ・これ何て呼びますか
- ・チョコミントアイス
- ・初めて自分の家と他人の家が違う、と意識した時
- ・「これはヤバかったな」という遅刻エピソード
- ・これ何て呼びますか Part2
- ・許せない心理テスト
- ・この人頭いいなと思ったエピソード
- ・牛、豚、鶏、どれか一つ食べられなくなるとしたら?
- ・あなたの習慣について教えてください!!
- ・ハマっている「お菓子」を教えて!
- ・高校三年生の合唱祭で何を歌いましたか?
- ・【大喜利】【投稿~11/1】 存在しそうで存在しないモノマネ芸人の名前を教えてください
- ・好きなおでんの具材ドラフト会議しましょう
- ・餃子を食べるとき、何をつけますか?
- ・あなたの「必」の書き順を教えてください
- ・ギリギリ行けるお一人様のライン
- ・10代と話して驚いたこと
- ・家の中でのこだわりスペースはどこですか?
- ・つい集めてしまうものはなんですか?
- ・自分のセンスや笑いの好みに影響を受けた作品を教えて
- ・【お題】引っかけ問題(締め切り10月27日(日)23時)
- ・大人になっても苦手な食べ物、ありますか?
- ・14歳の自分に衝撃の事実を告げてください
- ・架空の映画のネタバレレビュー
- ・「お昼の放送」の思い出
- ・昨日見た夢を教えて下さい
- ・ちょっと先の未来クイズ第4問
- ・【大喜利】【投稿~10/21(月)】買ったばかりの自転車を分解してひと言
- ・メモのコツを教えてください!
- ・CDの保有枚数を教えてください
- ・ホテルを選ぶとき、これだけは譲れない条件TOP3は?
- ・家・車以外で、人生で一番奮発した買い物
- ・人生最悪の忘れ物
- ・【コナン30周年】嘘でしょ!?と思った○○周年を教えて【ハルヒ20周年】
- ・あなたの習慣について教えてください!!
- ・都道府県穴埋めゲーム
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
ループを途中で抜けたいのですが。
-
do-while文が禁止される理由
-
ループの特定入力終了
-
Cプログラムが終了しない
-
入力した文字列から母音だけを...
-
For文の終了値を関数にしても問...
-
放電現象の2分法C言語プログラ...
-
プログラムで関数は使わない方...
-
入力した数値を倍々するプログラム
-
clock関数を利用した時間計測法...
-
Excel VBAで年度をまたぐ期間の...
-
break文でループを一気に抜ける...
-
for文while文の無限ループの違...
-
if文の中にfor文なのか、for文...
-
UWSCにてある一定の動作を無限...
-
桁数を求めるプログラム。
-
C言語 数字を削除する関数
-
ゲームオーバーのプログラム
-
C言語での引数の省略方法
-
信頼区間の1.96や1.65ってどこ...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
ループを途中で抜けたいのですが。
-
入力した文字列から母音だけを...
-
do-while文が禁止される理由
-
Excel VBAで年度をまたぐ期間の...
-
break文でループを一気に抜ける...
-
エクセルVBAで Do While (1)って?
-
入力した数値を倍々するプログラム
-
For文の終了値を関数にしても問...
-
UWSCにてある一定の動作を無限...
-
C言語forループが完結した場合...
-
n重のfor文にするには?
-
for文while文の無限ループの違...
-
Delphiで・・・
-
Cプログラムが終了しない
-
strstr()関数の実装内容について。
-
PAD図の書き方
-
放電現象の2分法C言語プログラ...
-
PIC のプログラムについて ど...
-
__asm int 3でのブレイクポイン...
-
線形探索(番兵法)のプログラ...
おすすめ情報