Java プログラミング スキル - データ構造とアルゴリズム「再帰」

Java プログラミング スキル - データ構造とアルゴリズム「再帰」

[[392763]]

コンセプト

簡単に言うと、再帰とは、毎回異なる変数を渡しながら、自身を呼び出すメソッドです。再帰は、プログラマーが複雑な問題を解決するのに役立ち、コードを整理することができます。

再帰はどのような問題を解決できますか?

  1. 8 人のクイーンの問題、ハノイの塔、階乗の問題、迷路の問題、ボールとバスケットの問題など、さまざまな数学の問題 (Google プログラミング コンテスト)。
  2. 再帰は、クイックソート、マージソート、バイナリ検索、分割統治アルゴリズムなどのさまざまなアルゴリズムでも使用されます。
  3. スタック->再帰コードで解決される問題は比較的簡潔です。

再帰に従うべきルール

  1. メソッドが実行されると、新しい保護された独立したスペース (スタック スペース) が作成されます。
  2. メソッドのローカル変数は独立しており、相互に影響を与えません。
  3. メソッド内で使用される変数が参照型変数(配列など)の場合、参照型のデータが共有されます。
  4. 再帰は再帰を終了するための条件に近づく必要があり、そうでない場合は無限再帰になります。
  5. メソッドが実行されるか、または return に遭遇すると、呼び出した人に結果が返されるという規則に従ってメソッドが返されます。同時に、メソッドが実行されるか返されると、メソッドも実行されます。

迷路問題を解くための再帰バックトラッキング

2 次元配列では、1 は壁を表します。指定された点から終点までのボールの経路を見つけます。

  1. パッケージ com.structures.recursion;
  2.  
  3. パブリッククラス MiGong {
  4. 公共 静的void main(String[] args) {
  5. //まず迷路と地図をシミュレートするための2次元配列を作成します
  6. int [][] マップ = 新しいint [8][7];
  7. //壁を表すために 1 を使用し、迷路の上、下、左、右を 1 に設定します
  8. ( int i = 0; i < 7; i++) {
  9. マップ[0][i] = 1;
  10. マップ[7][i] = 1;
  11. }
  12. ( int i = 0; i < 8; i++)の場合{
  13. マップ[i][0] = 1;
  14. マップ[i][6] = 1;
  15. }
  16. //バッフルを設定する
  17. マップ[3][1] = 1;
  18. マップ[3][2] = 1;
  19. // 出力マップ
  20. System.out.println ( "元のマップ" ) ;
  21. ( int i = 0; i < 8; i++)の場合{
  22. ( int j = 0; j < 7; j++)の場合{
  23. システム.out.print (map[i][j] + " " );
  24. }
  25. System.out.println( ) ;
  26. }
  27.  
  28. // 再帰バックトラッキングを使用してパスを見つける
  29. マップにWayを設定します。
  30. System.out.println ( "戦略に従って取られたパス" ) ;
  31. ( int i = 0; i < 8; i++)の場合{
  32. ( int j = 0; j < 7; j++)の場合{
  33. システム.out.print (map[i][j] + " " );
  34. }
  35. System.out.println( ) ;
  36. }
  37.  
  38. /*
  39. オリジナルマップ
  40. 1 1 1 1 1 1 1
  41. 1 0 0 0 0 0 1
  42. 1 0 0 0 0 0 1
  43. 1 1 1 0 0 0 1
  44. 1 0 0 0 0 0 1
  45. 1 0 0 0 0 0 1
  46. 1 0 0 0 0 0 1
  47. 1 1 1 1 1 1 1
  48. 戦略が辿った道
  49. 1 1 1 1 1 1 1
  50. 1 2 0 0 0 0 1
  51. 1 2 2 2 0 0 1
  52. 1 1 1 2 0 0 1
  53. 1 0 0 2 0 0 1
  54. 1 0 0 2 0 0 1
  55. 1 0 0 2 2 2 1
  56. 1 1 1 1 1 1 1
  57. */
  58. }
  59.  
  60. /**
  61. * 再帰バックトラッキングを使用してパスを見つけます。[6][5]をマップできる場合は、パスが見つかったことを意味します。
  62. * 規則: map[i][j] が 0 の場合、そのポイントは訪問されていないことを意味し、1 の場合、壁を意味し、2 の場合、通路を訪問できることを意味し、3 の場合、そのポイントは訪問済みだが訪問できないことを意味します。
  63. * 迷路を歩くときは、下→右→上→左と戦略(方法)を決め、通り抜けられない場合は戻る必要があります
  64. *
  65. * @param mapはマップを表します
  66. * @param i 行座標の開始位置
  67. * @param j 列座標の開始位置
  68. * @returnパスが見つかった場合はtrueを返し、そうでない場合はfalseを返します 
  69. */
  70. 公共 静的ブールsetWay( int [][] map, int i, int j) {
  71. (map[6][5] == 2)の場合{
  72. 戻る 真実;
  73. }それ以外{
  74. if (map[i][j] == 0){//現在のポイントを通過していない場合
  75. //戦略に従って、下->右->上->左に進みます
  76. map[i][j] = 2; //この地点を通過できると仮定する
  77. if (setWay(map, i + 1, j)) 下へ進む
  78. 戻る 真実;
  79. } else if (setWay(map, i, j + 1)){//右に進む
  80. 戻る 真実;
  81. } else if (setWay(map, i - 1, j)){//上へ進む
  82. 戻る 真実;
  83. } else if (setWay(map, i, j - 1)){//左に進む
  84. 戻る 真実;
  85. }それ以外{
  86. map[i][j] = 3; // この地点は行き止まりであり通過できないことを示します
  87. 戻る 間違い;
  88. }
  89. }それ以外{
  90. //map[i][j] != 0 の場合、1、2、3 のいずれかである可能性がある
  91. 戻る 間違い;
  92. }
  93. }
  94. }
  95. }

8つのクイーンの問題

8×8 のチェス盤に 8 つのクイーンを配置して、クイーン同士が攻撃し合わないようにする方法、つまり、同じ行、列、または対角線上に 2 つのクイーンがないようにする方法は、何通りありますか。

理論的には、チェス盤を表すには 2 次元配列を作成する必要がありますが、実際には、アルゴリズムを通じて 1 次元配列で問題を解決できます。arr[8]={0,4,7,5,2,6,1,3}、対応する arr の添え字は行、つまりクイーンを示します。arr[i]=val、val は i+1 番目のクイーンを示し、i+i 番目の行の val+1 列に配置されます。

  1. パッケージ com.structures.recursion;
  2.  
  3. パブリッククラス Queen8 {
  4. //女王が何匹いるかを示す
  5. プライベートint  最大= 8;
  6. //クイーン配置の結果を保存する配列を定義します。例: arr[8]={0,4,7,5,2,6,1,3}
  7. プライベートint [] 配列 = 新しいint [ max ];
  8.  
  9. 静的 整数 カウント= 0;
  10.  
  11. 公共 静的void main(String[] args) {
  12. Queen8 を新しい Queen8() に変換します。
  13. クイーン8.チェック(0);
  14. System.out.printf ( "合計%d通り\n" , count ); // 92通り
  15. }
  16.  
  17. //n番目のクイーンを配置する
  18. パブリックvoidチェック( int n) {
  19. if (n == max ) //n=8は前に配置されていることを意味する
  20. 印刷();
  21. カウント++;
  22. 戻る;
  23. }
  24. //クイーンを順番に並べて競合があるかどうかを判断します
  25. ( int i = 0; i < max ; i++) {
  26. //まず現在のクイーンnを新しい行の最初の列に置きます
  27. 配列[n] = i;
  28. //n 番目のクイーンを i 番目の列に配置するときに競合が発生するかどうかを判断します。
  29. もし(判断(n)){
  30. //次にn+1のクイーンを置いて再帰を開始します
  31. チェック(n + 1);
  32. }
  33. }
  34. }
  35.  
  36. // n 番目のクイーンを配置するときに、そのクイーンがすでに配置されているクイーンと競合するかどうかを確認します。
  37. プライベートブールジャッジ( int n) {
  38. ( int i = 0; i < n; i++)の場合{
  39. //array[i] == array[n]は、n番目のクイーンが前のクイーンと同じ列にあるかどうかを示します。
  40. //Math.abs (n - i) == Math.abs ( array[n] - array[i]) は、n番目のクイーンが前のクイーンと同じ対角線上にあるかどうかを示します。
  41. if (配列[i] == 配列[n] || Math.abs (n - i) == Math.abs (配列[n] - 配列[i])) {
  42. 戻る 間違い;
  43. }
  44. }
  45. 戻る 真実;
  46. }
  47.  
  48. //クイーンの位置を出力する
  49. パブリックボイドプリント(){
  50. ( int i = 0; i < 配列の長さ; i++) {
  51. システム.out.print (配列[i] + " " );
  52. }
  53. System.out.println( ) ;
  54. }
  55. }

【編集者のおすすめ】

  1. Ubuntu Linux に Windows 10 をインストールする最も簡単な方法
  2. システムのハードウェア情報を表示するためによく使用される Linux コマンド 9 つ (例と詳細な説明付き)
  3. この記事では、なぜこれほど多くの人が暗号通貨に投機しているのかを説明します。
  4. 10万スターを獲得したGitHubオープンソースプロジェクト10選
  5. Excel さえも凌駕します! WPS のこれらの機能をご存知ですか?

<<:  企業は AI、IoT、AR、VR、ブロックチェーン、ビッグデータをどのように活用して顧客を維持できるでしょうか?

>>:  アンドリュー・ングのパレートの法則: データの 80% + モデルの 20% = より優れた機械学習

ブログ    

推薦する

...

機械学習におけるモデルドリフト

今日、機械学習モデルはビジネス上の意思決定の主な原動力となっています。他のビジネス戦略と同様に、これ...

...

...

ロボットがIoTアプリケーションの範囲を拡大する方法

ロボットの学習能力と IoT アプリケーションの相互接続性は、実りある未来を約束します。モノのインタ...

コーディングが ChatGPT を圧倒します! UIUCと清華大学が共同で7BパラメータのMagicorderをリリース、コードデータの重みは完全にオープンソース

オープンソースの「ビッグコードモデル」が登場しました。 UIUC 清華大学の研究者チームは、70 億...

...

...

...

OPPOのコアアーキテクチャとインテリジェント成長アルゴリズムの応用

1. 業界背景スマートフォン業界は、典型的なハードウェア製造業として、人々の生活に密接に関係していま...

...

...

...

エキサイティング!自動運転におけるGPT-4Vの予備研究

この記事は、Heart of Autonomous Driving の公開アカウントから許可を得て転...