Java筆記試験強力トレーニング Niuke.com厳選プログラミング問題集03

単一の選択

以下の選択肢のうち、ショートタスク優先度(実行時間の最も短いタスクが先に実行される)を満たし、スタベーションが発生しないスケジューリングアルゴリズムは()です。

  • 先着順
  • B 高応答率優先
  • C タイムスライスの回転
  • D 非プリエンプティブな短いタスクが優先される

早い者勝ち(ECES、先着順)

最も単純なスケジューリング アルゴリズム。順番にスケジューリングします。

高応答率優先(HRRN、最高応答率次)

ジョブ/プロセスの待機時間とサービスに必要な時間を考慮して、各スケジューリング時に最初に各ジョブ/プロセスの応答率が計算され、応答率が最も高いジョブ/プロセスが選択され、サービスが提供されます。

高応答率優先スケジューリング アルゴリズムは、ECES (先着順アルゴリズム) と SE (短いジョブ優先アルゴリズム) の折衷アルゴリズムであり、ジョブの待ち時間とジョブの実行時間の両方を考慮し、短いジョブを無駄なく処理します。長いジョブの待機時間が長すぎる場合のスケジューリングのパフォーマンスが向上しまし

応答率 = (待ち時間 + サービス所要時間) / サービス所要時間

タイムスライスラウンドロビンスケジューリング(ラウンドロビン、RR)

タイムシェアリング システムのプロセス スケジューリングに使用されます。スケジュールされるたびに、レディ キューの先頭プロセスが常に選択され、システムによって事前に設定されたタイム スライスの間 CPU 上で実行できます。タイム スライス内で実行が完了しなかったプロセスは、スレッド キューの最後に戻されて再度キューに入れられ、次のスケジューリングを待ちます。

最短のジョブを優先(SJE、最短のジョブを優先)

SIE は非プリエンプティブ アルゴリズムです。最も短いジョブ/プロセスが最初に提供されます (いわゆる「最短」とは、必要なサービス時間が最も短いことを指します)。

システムがレディキュー内の最も高い優先順位を持つプロセスにプロセッサを割り当てると、プロセスは完了するまで実行を続けます。空腹感を引き起こしやすい。

次のオプションのうち、プロセスの優先度を下げるのに適切な時間は () です。

  • プロセス A のタイムスライスが不足する
  • プロセス B は I/O を完了し、準備完了キューに入りました。
  • C プロセスは永続的に準備完了キュー内にあります
  • D プロセスが準備完了状態から実行状態に変化する

スレッドの安全性を確保するためにロックを使用すると、活性エラーが発生する可能性があります。活性エラーには主に次のようなものがあります。

  • 行き詰まり
  • お腹が空いた
  • Cライブロック
  • D 上記のすべて

アクティビティの問題とは、CPU が長時間占有できないスレッドまたはプロセスを指します。

A. デッドロック: スレッドは互いにロックを保持し、互いのリソースが解放されるのを待ちます。その結果、誰も実行できなくなります。

B. ハングリー: 優先度の高いスレッドが毎回実行される場合、優先度の低いスレッドは決して実行されない可能性があります。

C. ライブロック: ライブロックとは、タスクまたは実行者がブロックされていないことを意味し、特定の条件が満たされないため、試行、失敗、試行、失敗が繰り返されます。

ライブロックとデッドロックの違いは、ライブロックのエンティティは状態を常に変更する、いわゆる「ライブ」であるのに対し、デッドロックのエンティティは待機しているように動作することです。ライブロックは自動的にロックを解除できますが、デッドロックはロックを解除できません。

キューにあるジョブの中で待機時間が最も長いジョブを最初に選択します。スケジューリング アルゴリズムは () です。

  • 先着順のスケジューリング アルゴリズム
  • B 高応答率優先スケジューリングアルゴリズム
  • C優先スケジューリングアルゴリズム
  • D 短いジョブの優先順位スケジューリング アルゴリズム

高優先度の優先スケジューリング アルゴリズム

これは、緊急のジョブ(優先度の高いタスク)をシステムに入ってから優先的に処理できることを意味します。

プロセスとスレッドの説明については、以下が正しいです ()

  • A 親プロセス内のすべてのスレッドは同じアドレス空間を共有し、親プロセスのすべての子プロセスは同じアドレス空間を共有します。

  • B プロセス内のメインスレッドのステータスを変更すると、他のスレッドの動作に影響しますが、親プロセスのステータスを変更しても、他の子プロセスには影響しません。

  • C マルチスレッドではデッドロックが発生するが、マルチプロセッシングではデッドロックが発生しない

  • D 上記の選択肢はどれも正しくありません

A. 親プロセスと子プロセスには独自の独立したアドレス空間があります。

B. メインスレッドとサブスレッドが並列関係にある場合、依存関係はありません。親プロセスの終了時に子プロセスに終了を通知するなど、親プロセスのステータスを変更すると、子プロセスの状態に影響を与える可能性があります。通知がない場合、子プロセスには影響しません。

C. 複数のプロセスが互いに必要なリソースを占有し、同時に互いのリソースを要求し、要求を取得する前に占有しているリソースを解放しない場合、デッドロックが発生します。つまり、プロセスを同期できません。 。

プロセッサ上で 2 つのスレッドを実行することに関する次の記述のうち、正しいものはどれですか?

  • A あるスレッドが別のスレッドのプログラム カウンター (プログラム カウンター) を変更できる
    B あるスレッドが別のスレッドのスタックを読み書きできない
    C あるスレッドが別のスレッドのレジスタを読み書きできる
    D 上記のいずれでもない

改ページエラーを減らすにはどうすればよいでしょうか?

  • A プロセスが CPU を占有する傾向がある
    B アクセスの局所性 (参照の局所性) がプロセス要件を満たしている
    C プロセスが I/O を占有する傾向がある
    D 最短の残り時間に基づいたスケジューリング メカニズムを使用する

ページ フォールト:ページ フォールトは、実際にはページ フォールト例外またはページ フォールト割り込みと翻訳される必要がありますが、仮想メモリの導入後の概念です。

仮想メモリ:オペレーティング システムは起動後、メモリ内に仮想アドレス テーブルを維持し、プロセスに必要な仮想アドレスが仮想アドレス テーブルに記録されます。プログラムがロードされて実行されるとき、その一部だけがメモリにロードされ、残りの部分は必要に応じてディスクからロードされます。特定の命令またはデータを実行する必要があるが、それらがメインメモリにないことが判明した場合、ページフォルト割り込みが生成され、システムは命令またはデータが配置されているページを補助メモリからメモリに転送します。 。

B: 局所性が良い; 次に探しているものは現在の記憶の前後に遠くなく、同じページ上にある可能性が高いため、頻繁にページを変更する必要がなく、ページ変更エラーが少なくなります。

AC はパフォーマンスを向上させるためのものです。D もページ送りエラーの削減とは何の関係もありません

プログラムが必要とするサイズに対してシステムのメモリが不足している場合、プログラムは実行できません。

  • 間違った
    B正しい

通常「ストレージ保護」と呼ばれるものの基本的な意味は () です。

  • A メモリハードウェアの損傷を防ぐ
    B プログラムがメモリ内で失われるのを
    防ぐ C プログラム間の相互国境を越えたアクセスを防ぐ
    D プログラムの覗き見を防ぐ

仮想ストレージ テクノロジを使用するストレージ システムでは、マルチタスク オペレーティング システムが複数の異なるプログラムをメイン メモリに転送して同時に実行することがよくあります。

  1. まず、これらのプログラムが相互に上書きしないようにする必要があります。

  2. プログラムは、他のプログラムのデータや、自分に割り当てられていないメイン メモリの領域にアクセスすることはできません。

  3. 1 つのプログラムにエラーが発生しても、他のユーザー プログラムやシステム プログラムに損傷を与えることはありません。

上記の条件を満たすために、主記憶上のプログラムを制限的に保護する技術をストレージ保護といいます。ストレージ領域の保護は、主にアドレスが境界を越えるのを防ぐことです

以下のプロセススケジューリングアルゴリズム()では、長時間プロセスがスケジューリングできない状況(スタベーション現象)が発生する可能性があります。

  • A 非プリエンプティブ静的優先方式
    B プリエンプティブ静的優先方式
    C タイムスライスローテーションスケジューリングアルゴリズム
    D 非プリエンプティブ動的優先方式

プリエンプティブ/プリエンプティブ
タイプ 現在のプロセスが実行中に、重要または緊急の優先度の高いプロセスが到着すると (ステータスが準備完了である必要があります)、現在実行中のプロセスはプロセッサを強制的に放棄し、システムは即座にプロセッサを割り当てます。新しく到着したプロセスへ。

静的な優先度はプロセスの作成時に決定され、プロセスの存続期間中は変更されません

動的優先度:
プロセスの作成時に与えられる優先度は、より良いスケジューリング パフォーマンスを得るために、プロセスの進行または待機時間の増加に応じて変更できます。待機時間が増加するにつれて、優先度も増加します。

A. 非プリエンプティブ静的優先度方式: 優先度は変更されません。優先度が最も低いスレッドが待機している場合、優先度が高いプロセスの実行が終了した後、そのプロセスが実行されます。

B. プリエンプティブ静的優先方式: プリエンプティブ方式とは、優先度の高いものが CPU の実行能力を奪うことができることを意味します。低優先度のプロセスが実行され、高優先度のプロセスがレディ状態にある場合、CPU は高優先度のプロセスをプリエンプティブに実行し、低優先度のプロセスはプリエンプトされてレディ状態になります。優先度の高いプロセスが常に準備ができている場合は、優先度の低いプロセスが待機している可能性があります。

C.タイム スライス ローテーション スケジューリング アルゴリズム:実行タイム スライスが完了すると、実行されたプロセスはループの待機キューの最後に配置されます。ループであるため、順番が来るチャンスがあります。

D. 非プリエンプティブ動的優先方式: 非プリエンプティブですが、プロセスが待機している場合、その優先度が動的に増加し、CPU の実行権を取得できます。

セマフォの現在の値が -4 の場合、システム内にセマフォを待機しているプロセスが存在することを意味します。

  • A 4
    B 3
    C 5
    D 0

これがセマフォの P および V 操作です: pv 操作はウェイトおよびシグナルとも呼ばれ、主に演算プロセス中にプロセスによって制御される情報量の加算および減算を制御します。

wait の使用法: wait(num)、num はターゲットパラメータです

  • wait の機能は、情報量を 1 つ減らすことです。情報量 >= 0 の場合、プロセスは実行を継続しますが、それ以外の場合、プロセスは待機状態になり、待機キューに入れられます。

シグナルの使用法: signa1(num)、num はターゲットパラメータです

  • シグナルの役割は情報量を1つ増やすことです。情報量が >0 の場合、プロセスは実行を継続しますが、そうでない場合は、キュー内でセマフォを待っている最初のプロセスが解放されます。

セマフォは現在利用可能なリソースの数を表します。セマフォが負の場合、リソースを申請するプロセスは待機することしかできません。したがって、負のセマフォの数は、リソースを申請したものの、使用可能なリソースがなく、待機することしかできないプロセスの数を示します。

ベース アドレッシング モードでは、オペランドの実効アドレスは ____ です。

  • A ベースレジスタの内容+形式アドレス(変位量)
    B プログラムカウンタの内容+形式アドレス
    C インデックスレジスタの内容+形式アドレス
    D レジスタの内容+形式アドレス

ベース アドレッシング モードは、主にプログラムの動的配置の問題を解決するために使用されます。

ベース アドレス アドレッシングでは、CPU のベース アドレス レジスタの内容を命令フォーマットの正式なアドレスに追加して、オペランドの実効アドレスを形成します。

基本的に、ベースアドレスレジスタ + 正式アドレスを通じてメモリの仮想アドレスを形成します。

システム内にユーザーレベルのスレッドのみが存在する場合、プロセッサのスケジューリング単位は () です。

  • A スレッド
    B プロセス
    C プログラム
    D ジョブ

システムにユーザー モード スレッドのみがある場合、そのスレッドはオペレーティング システムには表示されず、オペレーティング システムはプロセスのスケジュールのみを実行できます。システム内に
カーネル モード スレッドがある場合、オペレーティング システムはスレッドごとにスケジュールできます。

C: プログラムは静的な実行ファイルであり、プロセスは動的です。実行ファイルの内容がメモリにコピーされ、CPU を占有して実行され、プロセスになります。D. ジョブ: 通常、ジョブには複数のプロセスが含まれます
いくつかのプロセスが連携してタスク、つまり宿題を完了します。

オンライン サーバーは通常、大量のデータを保存するデータベースを読み取る必要があります。サーバーの処理速度を向上させるためには、通常、キャッシュを追加する必要がありますが、次のような場合はキャッシュの使用には適していません。

  • A. データベース内の各データは、アクセスされる確率がほぼ同じであり、独立している
    B. マルチスレッド メカニズムを使用するサービス
    C. 単一スレッドのサイズが小さすぎる
    D. サービスアクセス数が多い。

データベース内の各データがアクセスされる確率はほぼ等しく、一般にキャッシュ領域は小さく、これ以上のデータを保存することは不可能であるためです。未確認の予測のためにクエリを実行する必要があるデータの場合、最近アクセスしたデータをキャッシュに入れてもあまり意味がないため、キャッシュを増やしても大きな効果はありません。BCD は効率を向上させることができます

マルチスレッドをサポートするシステムでは、プロセス P によって作成された複数のスレッドは () を共有できません。

  • A プロセス P のコード セグメント
    B プロセス PC で開かれたファイル
    C プロセス P のグローバル変数
    D プロセス P のスレッドのスタック ポインタ

D はスレッドのプライベートです

オペレーティング システムにおける競合とデッドロックの関係について正しいのは次のうちどれですか?

  • A 競争は必ずデッドロックを引き起こす
    B デッドロックは間違いなく競争によって引き起こされる
    C 競争はデッドロックを引き起こす可能性がある
    D デッドロックを防ぐと競争を妨げることができる

デッドロックに必要な 4 つの条件:

  1. 相互に排他的な条件: リソースは一度に 1 つのプロセスによってのみ使用できます。
  1. 要求と保持の条件: リソースの要求によりプロセスがブロックされた場合、プロセスは取得したリソースを保持します。

  2. 非剥奪条件: プロセスによって取得されたリソースは、使い果たされる前に強制的に剥奪することはできません。

  3. 循環待機条件: 複数のプロセス間で先頭から末尾までの循環待機リソース関係が形成されます。

A. ロックが競合しても上記の条件を満たさない場合、デッドロックは発生しません。

B. スレッド A とスレッド B のロック: スレッド A がロックを取得します。しかし、ロックを解除するのを忘れて、再度ロックをしたくなった結果、スレッド A とスレッド B が両方ともデッドロック状態に陥りました。現時点では競合するロックはありません

C. 競合がデッドロックの上記 4 つの条件を満たしている場合、デッドロックが発生するため、競合が発生する可能性があります。

D. 同じリソース上で複数のプロセスまたはスレッドが動作している場合は、ロックが必要になる必要があります。つまり、競合が発生する必要があります。

同時実行は並列処理の別の表現ですが、原理は同じです。

  • 間違った
    B正しい

同時実行性: 1 つの CPU の下で、複数のプロセスがタイム スライス ローテーション スケジューリングを使用します。一定期間内に、複数のプロセスを進めることができます。これを同時実行性と呼びます。CPU は、プロセスが 1 つずつ実行されているのを認識しますが、肉眼では見えません。

並列処理: 複数のプロセスが複数の CPU 上で同時に実行されます。これを並列処理と呼びます。

スレッドを切り替えるとプロセスが切り替わります。

  • 間違った
    B正しい

プロセスには複数のスレッドが含まれる場合もあります。同じプロセス内のスレッド間の切り替えではプロセスの切り替えは発生しませんが、異なるプロセス内のスレッドの切り替えではプロセスの切り替えが発生します。

オペレーティング システムのすべてのプログラムはメモリに常駐します。

  • Aは間違っています
  • 明るい

イベントを待機しているプロセスの場合、それらを外部メモリ (一部またはすべて) にスワップして、より多くのメモリを解放して新しいプロセスをロードし、CPU リソースを最大限に活用することができます。

論理アドレス変換処理の物理アドレスを()と呼びます。

  • A アドレスの割り当て
    B アドレスのマッピング
    C アドレスの保護
    D 範囲外のアドレス

論理アドレス: メモリ内の仮想アドレス。物理アドレス: メモリースティック上の実際のアドレス

A: プロセスの作成時にメモリが割り当てられます。

B: アドレス マッピング: 命令の実行時に CPU がストレージ ユニットに正しくアクセスできるようにするには、ユーザー プログラム内の論理アドレスを、実行時にマシンが直接アドレス指定する物理アドレスに変換する必要があります。

C: 複数のプロセスの間では、他人のメモリを使用することはできません。

D: 他のプロセスのメモリにアクセスしました

Unix システムでは、() 状態のプロセスが最も簡単に実行できます。

  • A 補助ストレージのスリープ
    B メモリのスリープ
    C メモリの準備完了
    D 補助ストレージの準備完了

ここに画像の説明を挿入します

()内にはプロセスの制御情報と記述情報が格納されます。

  • A JCB
    B PCB
    C AFT
    D SFT

制御プロセスの動作を記述するために、システム内のプロセスの管理・制御情報を格納するデータ構造をプロセス制御ブロック(PCB Process ControlBlock)と呼び、プロセス管理と制御にとって最も重要なデータ構造です。各プロセスには PCB があり、プロセスが作成されると PCB が確立され、これはプロセスがキャンセルされるまでプロセスを実行するプロセス全体に伴います。

PCB には通常次のものが含まれます。

  1. プログラム ID (PID、プロセス ハンドル): これは一意であり、各プロセスは PID に対応する必要があります。PID は通常、整数です。
  2. 特性情報:一般にシステムプロセス、ユーザープロセス、カーネルプロセスなどに分けられます。
  3. プロセスのステータス: 実行中、準備完了、ブロック済み、プロセスの現在の実行ステータスを示します。
  4. Priority: CPU 制御を取得するための優先レベルを示します。
  5. 通信情報: オペレーティング システムが通信チャネルを提供するため、プロセス間の通信関係を反映します。
  6. オンサイト保護ゾーン: ブロックされたプロセスを保護するために使用されます
  7. リソース要件、割り当て制御情報

() の場合、システムがデッドロックします。

  • A 複数のプロセスがリソースの競合により、占有リソースの解放を延々と待ち続けている
    B 複数のプロセスが同時にブロックされている C
    コンピュータシステムに重大な障害が発生している
    D リソースの数が実際のリソースの数よりはるかに少ないプロセスの数、またはプロセスによって同時に要求されたリソースの数がリソースを大幅に超えています。

デッドロックは、2 つのスレッドまたは複数のスレッドがお互いにリソースを解放するのを待っていて、お互いに譲歩することを拒否し、結果としてデッドロックが発生する場合に発生します。

D: プロセスはリソースの競合に失敗し、ブロックされています。

システムがスラッシングしている場合に取られる効果的な対策は ( ) です。
Ⅰ.処理の一部を中止する Ⅱ.ディスクスワップ領域の容量を増やす Ⅲ.ユーザープロセスの優先度を上げる

  • A のみ Ⅰ
    B のみ Ⅱ
    C のみ Ⅲ
    D のみ Ⅰ、Ⅱ

スワップ機能を備えたオペレーティングシステムでは、通常、外部ストレージはファイル領域とスワップ領域に分かれています前者はファイルの保存に使用され、後者はメモリからスワップアウトされたプロセスの保存に使用されます。

スラッシング現象は、スワップアウトされたばかりのページがすぐに再びアクセスされることを意味します。そのため、他のページを入れ替える必要があり
、すぐにそのページにアクセスしてしまうため、ページを入れ替えるのが面倒で、ほとんどの時間がページ入れ替えに費やされてしまいます。

Ⅰ:一部の処理を元に戻すことで、使用するページ数を減らし、ジッターを防ぐことができます。

II および III: スワップ領域のサイズとセッションの優先順位はジッターとは関係ありません。ページは仮想メモリに関連しており、

スレッドに関する次の記述のうち、間違っているものはどれですか ()

  • A 時間のかかる操作にはスレッドを使用して、プログラムの応答を改善します。
  • B メモリを消費する操作では、スレッドを使用してメモリ使用率を向上させます。
  • C マルチ CPU システムはスレッドを使用して CPU 使用率を向上させる
  • D 並列操作ではスレッドを使用します。たとえば、c/s アーキテクチャでは、サーバー プログラムは各クライアントの要求に応答するスレッドを作成します。

B: スレッドはプロセスの一部であり、メモリ使用率を向上させることが間違っていると言うのは間違いです。

固定ブロックサイズファイルシステムのブロックサイズを大きく設定すると()が発生します。

  • ディスク スループットが向上し、ディスク スペース使用率が低下
    B ディスク スループットが向上し、ディスク
    スペース使用率が向上 C ディスク スループットが低下し、ディスク スペース使用率が向上
    D ディスク スループットが低下し、ディスク スペース使用率が低下

ファイルはブロックに保存されます。ブロック サイズを大きく設定すると、一度に読み取れるデータが増え、ディスクのスループットが向上します。ただし、ファイル全体がブロック全体を占有できない場合があり、使用率が低下します。

プロセスの次の 4 つの特性のうち、最も基本的な特性は () です。

  • A 同時性
    B ダイナミクス
    C 独立性
    D 非同期性

A.同時実行性:メモリ内に共存し、一定期間内に同時に実行される複数のプロセス エンティティを指します。同時実行性はプロセスの重要な機能であり、オペレーティング システムの重要な機能でもあります。

B.ダイナミクス:プロセスの本質はプロセス エンティティの実行プロセスであるため、ダイナミクスはプロセスの最も基本的な機能です。

C.独立性:プロセス エンティティは、独立して実行され、リソースを独立して割り当て、スケジューリングを独立して受け入れる基本単位です。

D.非同期:独立した予測不可能な速度で順次進行するプロセス、または非同期で実行されるエンティティを指します。

プロセスのスケジューリングとは、()からプロセスを選択して稼働させることです。

  • A 準備完了キュー
    B 待機キュー
    C ジョブバックアップキュー
    D 送信キュー

B.待機キュー:頻繁にポーリングを行わずに特定のイベントが発生するまでスレッドを待機させるために使用されます。プロセスは待機中にスリープし、何かが発生するとカーネルによってウェイクアップされます。

C.ジョブ バックアップ キュー:オペレーティング システムは、まず外部ストレージ内のバックアップ キューから特定のジョブを選択してメモリに転送し、それらのジョブ用のプロセスを作成し、必要なリソースを割り当てます。次に、新しく作成したプロセスを準備完了キューに挿入し、実行の準備をします。

キャッシュに関する次の記述のうち、間違っているものはどれですか?

  • A キャッシュを設定する目的は、CPU とメインメモリ間の速度一致の問題を解決することです。
    B キャッシュを設定する理論的根拠は、プログラムアクセスの局所性の原則です。
    C キャッシュとメインメモリは均一にアドレス指定され、キャッシュのアドレス空間はメイン メモリの一部
    D キャッシュの機能はハードウェアによって実装され、プログラマには透過的です。

A. Cache が表示される理由は、CPU とメインメモリ間の速度マッチング問題を解決するためです (CPU 速度 > キャッシュ速度 > メインメモリ速度)。

B. プログラム アクセスの局所性の原則は、プログラムが実行されている一定期間中、プログラムがアクセスするコードまたはデータのほとんどが特定の領域に集中するというものです。

C. キャッシュのアドレスとメインメモリのアドレスは別のものであり、統一的にアドレス指定されておらず、関連性もありません。

D.cache はハードウェアによって実装されます。

メモリスラッシング(Thrashing)とは()

  • A 非常に頻繁なページング アクティビティ
    B 非常に高い CPU 実行アクティビティ
    C 非常に長い実行プロセス
    D 非常に大きな仮想メモリ

メモリの仮想管理の概念により、ページが頻繁に置き換えられると、システム全体の効率が急激に低下し、この現象はメモリ ジッターと呼ばれます。
ジッターは通常、メモリ割り当てアルゴリズムが不十分であることメモリが小さすぎること、またはプログラム アルゴリズムが不十分であることが原因で発生し、ページが頻繁にメモリの内外に転送されることになります。

すべての非プリエンプティブ CPU スケジューリング アルゴリズムの中で、最適なシステム平均応答時間は ( )

  • A リアルタイム スケジューリング アルゴリズム
    B ショート タスク優先アルゴリズム
    C タイム スライス ローテーション アルゴリズム
    D 先着順アルゴリズム

応答時間は、タスクの到着から処理中のタスクの開始 (応答) までの時間です。ターンアラウンドタイムとは、到着してから処理が完了するまでの時間です。

A**.リアルタイム スケジューリング アルゴリズム:** は、限られた応答時間内で必要なレベルのサービスを提供するシステムの能力を指します。システムの時間制約が満たされていない場合、システム エラーが発生します。

B.短いタスク優先アルゴリズム:実行時間の短いタスクが最初に実行されます。

C.タイム スライス ローテーション アルゴリズム:システムはレディ キュー内のプロセスをスケジュールし、各プロセスにタイム スライスが割り当てられ、クロック割り込みを使用してプロセスの定期的な切り替えが実行されます。

D.先着順アルゴリズム:スケジューリングは先着順で行われます。

上記のスケジューリング アルゴリズムのうち、タイム スライス ローテーション アルゴリズムはプリエンプティブ スケジューリング アルゴリズムです。

すべてのプロセスがほぼ同時に到着する場合、タスク優先度の短いスケジューリング アルゴリズムの平均待ち時間と平均ターンアラウンド タイムが最も短くなります。

次のコードでは、t2 スレッドが開始される前に t1 スレッドが開始されたとします。コードの出力は () です。

public class TestDemo {
     
     
public static void main(String[]args)throws Exception {
     
     
final Object obj = new Object();
Thread t1 = new Thread() {
     
     
 public void run() {
     
     
     synchronized (obj) {
     
      // 1.
         try {
     
     
             obj.wait(); // 2. 释放对象锁,让当前线程等待(t1)
             // 6. t1 线程再申请 obj 锁, 申请成功,则继续往下地行
             System.out.println("Thread 1 wake up.");
         } catch (InterruptedException e) {
     
     
         }
     }
 }
};
t1.start();
Thread.sleep(1000);//We assume thread 1 must start up within 1 sec.
Thread t2 = new Thread() {
     
     
 public void run() {
     
     
     synchronized (obj) {
     
      // 3.
         obj.notifyAll(); // 4、通知 obj 对象 wait 等待的线程
         System.out.println("Thread 2 sent notify.");
     } // 5、这里释放锁 通知 obj
 }
};
t2.start();
}
}
  • A スレッド 1 がウェイクアップ スレッド 2 が通知を送信
    B スレッド 2 が通知を送信 スレッド 1 がウェイクアップ
    CA と B は両方とも可能
    D プログラムは出力がなくスタックしている。

次の記述のうち正しいものはどれですか?

  • A ページ ストレージ管理では、ユーザーはプログラムを複数の等しいページに分割する必要があります
    B すべてのプロセスが一時停止されると、システムはデッドロックに陥ります
    C システム コールの実行が中断される可能性があります
    D プロセスの優先順位番号はプロセスによってスケジュールされます 重要な基本は、必ず行う必要がありますプロセスの実行状況に応じて動的に変更される

A. ページの分割はオペレーティング システムによって行われます。

B. システムは、デッドロックに入る 4 つの条件を満たす必要があります: 相互排他、ループと待機、非剥奪なし、要求と保留、すべてのプロセスが中断されていますが、これは、これらのプロセス間のリソース呼び出しとループ待機の間に関係があることを意味するものではありません。 . 一部のプロセス タイマーが切れると自動的に起動する場合があります。

C: ユーザー プログラムがシステム関数を呼び出しているため、より高い優先度のプロセスによって中断される可能性があります。

D. 静的な優先順位のスケジューリングがあります。

次の方法のうち、___ はプログラムのチューニングに使用できませんか?

  • A データ アクセス方法を改善してキャッシュ ヒット率を向上させる
    B マルチスレッドを使用して I/O 集中型の操作の効率を向上させる
    C データベース接続プールを使用して直接データベース アクセスを置き換える
    D 反復を使用して再帰を置き換える
    E 複数のリモート呼び出しを結合して送信する
    F 冗長データの共有によりアクセス効率が向上

B I/O 集中型のアプリケーションであれば、問題ありません。


プログラミングに関する質問

生地のストリップをカットします

内側にいくつかの模様が入った花柄の布と、内側にいくつかの模様が入った直接使用できる小さな装飾ストリップ。与えられた花柄生地のストリップと小さな装飾ストリップについて、花柄生地のストリップから切り取れる小さな装飾ストリップの数を計算しますか?

説明を入力してください:

输入包含多组数据。

每组数据包含两个字符串s,t,分别是成对出现的花布条和小饰条,其布条都是用可见ASCII字符表示的,可见的ASCII字符有多少个,布条的花纹也有多少种花样。花纹条和小饰条不会超过1000个字符长。

出力の説明:

对应每组输入,输出能从花纹布中剪出的最多小饰条个数,如果一块都没有,那就输出0,每个结果占一行。

入力

abcde a3
aaaaaa aa

出力

0
3
import java.util.*;

public class Main {
    
    
    private static int cut(String s, String t) {
    
    
        int i = s.indexOf(t);
        if (i == -1) {
    
    
            return 0;
        }
        return 1 + cut(s.substring(i + t.length()), t);
    }
    
    public static void main(String[] args) {
    
    
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNext()) {
    
    
            String s = scanner.next();
            String t = scanner.next();
            System.out.println(cut(s, t));
        }
    }
}
import java.util.*;

public class Main {
    
    
    public static void main(String[] args) {
    
    
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNext()) {
    
    
            String s = scanner.next();
            String t = scanner.next();
            int count = 0;
            while (s.contains(t)) {
    
    
                s = s.replaceFirst(t, ""); // replaceFirst 替换第一个
                count++;
            }
            System.out.println(count);
        }
    }
}

ゲストは雲のようにやってくる

NowCoder が朝食のお店をオープンしました この店のお客さんには不思議な習慣があって、一度この店に朝食を食べに来ると毎日来てしまうというもので、二日間この店で朝食を食べるとみんなも私も新しい友達を連れて毎日それを味わってもらいます。
その結果、この店の顧客の数は 1 人から数百人、数千人にまで増加しました。1、1、2、3、5... さて、NowCoder はあなたに、顧客の総数を計算するのを手伝ってもらいたいと考えています
。一定期間に販売した顧客の数 提供する朝食の数 (ゲスト 1 人につき 1 回の朝食のみと仮定)
説明を入力してください:

测试数据包括多组。
每组数据包含两个整数from和to(1≤from≤to≤80),分别代表开店的第from天和第to天。

出力の説明:

对应每一组输入,输出从from到to这些天里(包含from和to两天),需要做多少份早餐。
import java.util.*;
import java.math.*;

public class Main {
    
    
    public static void main(String[] args) {
    
    
        // 可以用 long[]
        // 1 1 2 3 5...
        BigDecimal[] bigDecimal = new BigDecimal[80];
        bigDecimal[0] = new BigDecimal("1");
        bigDecimal[1] = new BigDecimal("1");
        for (int i = 2; i < 80; i++) {
    
     // 数组 第 3 个下标为 2
            bigDecimal[i] = bigDecimal[i - 1].add(bigDecimal[i - 2]);
        }
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNext()) {
    
    
            int from = scanner.nextInt();
            int to = scanner.nextInt();
            BigDecimal sum = new BigDecimal("0");
            for (int i = from - 1; i < to; i++) {
    
    
                sum = sum.add(bigDecimal[i]); // sum = 
            }
            System.out.println(sum);
        }
    }
}

受信者リスト

NowCoder は毎日多くの顧客にメールを書いています。ご存知のとおり、電子メールに複数の受信者が含まれる場合、受信者名はカンマとスペースで区切られます。受信者名にもスペースまたはカンマが含まれる場合は、名前を二重引用符で囲む必要があります。
次に、一連の受信者名を渡し、対応する受信者リストを作成するのを手伝ってもらいます。
説明を入力してください:

输入包含多组数据。

每组数据的第一行是一个整数n (1≤n≤128),表示后面有n个姓名。

紧接着n行,每一行包含一个收件人的姓名。姓名长度不超过16个字符。

出力の説明:

对应每一组输入,输出一行收件人列表。

入力

3
Joe
Quan, William
Letendre,Bruce
2
Leon
Kewell

出力

Joe, "Quan, William", "Letendre,Bruce"
Leon, Kewell
import java.util.*;

public class Main {
    
    
    public static void main(String[]  args) {
    
    
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNext()) {
    
    
//            String ret = scanner.nextLine(); // n 读一行 防止换行作为了一个 s
//            int n = Integer.valueOf(ret);
            int n = scanner.nextInt();
            scanner.nextLine(); // 或者再读 line
            while (n-- != 0) {
    
    
                String s = scanner.nextLine();
                if (s.contains(",") || s.contains(" ")) {
    
    
                    if (n == 0) {
    
     // 最后一个没有逗号
                        System.out.print("\"" + s + "\"");
                    } else {
    
    
                        System.out.print("\"" + s + "\"" + ", ");
                    }
                } else {
    
    
                    if (n == 0) {
    
    
                        System.out.print(s);
                    } else {
    
    
                        System.out.print(s + ", ");
                    }
                }
            }
            System.out.println();
        }
    }
}

ウサギを育てる

成熟したウサギは1日に1匹の子を産むことができます。各うさぎの成熟期間は1日です。誰かが小さなウサギを引き取りました。N 日目後に彼は何匹のウサギを手に入れるでしょうか?

説明を入力してください:

测试数据包括多组,每组一行,为整数n(1≤n≤90)。

出力の説明:

对应输出第n天有几只兔子(假设没有兔子死亡现象)。

入力

1<br/>2

出力

1<br/>2
import java.util.*;
import java.math.*;

public class Main {
    
    
    public static void main(String[] args) {
    
    
        // 可以用 long
        // 此题是 1 2 3 5...
        BigDecimal[] bigDecimal = new BigDecimal[90];
        BigDecimal b1 = new BigDecimal("1");
        BigDecimal b2 = new BigDecimal("1");
        BigDecimal b3 = b1;
        for (int i = 0; i < 90; i++) {
    
    
            bigDecimal[i] = b3;
            b1 = b2;
            b2 = b3;
            b3 = b1.add(b2);
        }
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNext()) {
    
    
            int n = scanner.nextInt();
            System.out.println(bigDecimal[n - 1]);
        }
    }
}

新斉五月ウサギ

うさぎは一対います 生後5ヶ月目から毎月一対のうさぎを産みます 子うさぎが成長して5ヵ月目になると毎月一対のうさぎを産みます死なないので、n 番目の月を尋ねてください。ウサギのつがいの数は何ですか。

对数: 1  1  1  1  2  3  4  5  7  10  14  19  26  36  50  69

增数: 0  0  0  0  1  1  1  1  2   3    4    5    7   10  14  19

コード:

public class TestDemo {
    
    
    private static int fib2(int n) {
    
    
        if (n == 1 || n == 2 || n == 3 || n == 4) {
    
    
            return 1;
        }
        return fib2(n - 1) + fib2(n - 4);
    }

    private static void fib(int n) {
    
    
        int[] array = new int[n];
        for (int i = 0; i < 4; i++) {
    
    
            array[i] = 1;
        }
        for (int i = 4; i < n; i++) {
    
    
            array[i] = array[i - 1] + array[i - 4];
        }
        System.out.println(Arrays.toString(array));
    }

    public static void main(String[] args) {
    
    
        fib(16); // [1, 1, 1, 1, 2, 3, 4, 5, 7, 10, 14, 19, 26, 36, 50, 69]
    }
}

年次総会の抽選 - 間違った配置の問題

今年の全社年次総会の賞品は特に豪華ですが、当選のルールは非常に奇妙です:
\1. まず、従業員全員が自分の名前を書いた紙幣を抽選箱に入れます。
\2. すべての紙幣が抽選された後、追加、それぞれ その人は箱からメモを取ります;
\3. 書かれたメモがその人の名前であれば、「おめでとうございます、賞を獲得しました!」
今度はパーティーに参加する人の数を教えてください、確率を計算してください誰が受賞したのか?
説明を入力してください:

输入包含多组数据,每组数据包含一个正整数n(2≤n≤20)。

出力の説明:

对应每一组数据,以“xx.xx%”的格式输出发生无人获奖的概率。

入力

2

出力

50.00%

【問題解決のアイデア】

ここに画像の説明を挿入します

import java.util.*;

public class Main {
    
    
    public static void main(String[] args) {
    
    
        long[] d = new long[21]; // 第 n 个人错排总数
        d[0] = 0;
        d[1] = 0;
        d[2] = 1;
        long[] f = new long[21]; // n 的阶乘
        f[0] = 1;
        f[1] = 1;
        f[2] = 2;
        for (int i = 3; i <= 20; i++) {
    
    
            d[i] = (i - 1) * (d[i - 1] + d[i - 2]);
            f[i] = f[i - 1] * i;
        }
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNextInt()) {
    
    
            int n = scanner.nextInt();
            double ans = 100.0 * d[n] / f[n];
            System.out.printf("%.2f%%\n", ans);
        }
    }
}

CCリスト

NowCoder は毎日多くの電子メールを処理しますが、受信者リストには含まれておらず、場合によっては単にコピーされているだけです。彼は、これらの CC メールの重要性が受信者リストにあるメールよりも低いと考えているため、これらの二次メールをフィルタリングして除外し、重要なメールを優先する必要があります。
CC のリストが表示されるので、対象のユーザーが CC リストに含まれているかどうかを確認してください。
説明を入力してください:

输入有多组数据,每组数据有两行。

第一行抄送列表,姓名之间用一个逗号隔开。如果姓名中包含空格或逗号,则姓名包含在双引号里。总长度不超过512个字符。

第二行只包含一个姓名,是待查找的用户的名字(姓名要完全匹配)。长度不超过16个字符。

出力の説明:

如果第二行的名字出现在收件人列表中,则输出“Ignore”,表示这封邮件不重要;否则,输出“Important!”,表示这封邮件需要被优先处理。

入力

Joe,Kewell,Leon
Joe
"Letendre, Bruce",Joe,"Quan, William"
William

出力

Ignore
Important!
import java.util.*;

public class Main {
    
    
    public static void main(String[] args) {
    
    
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNext()) {
    
    
            String s = scanner.nextLine();
            String name = scanner.nextLine();
            boolean flag = true;
            for (int i = 0; i < s.length(); i++) {
    
    
                StringBuilder sb = new StringBuilder();
                if (s.charAt(i) == '\"') {
    
     // 名字里有空格或逗号 找到另一个双引号
                    i++; // 跳过此双引号
                    while (i < s.length() && s.charAt(i) != '\"')
                        sb.append(s.charAt(i++));
                } else {
    
     // 普通名字 找到逗号为之
                    while (i < s.length() && s.charAt(i) != ',') {
    
    
                        sb.append(s.charAt(i++));
                    }
                }
                if (sb.toString().equals(name)) {
    
    
                    System.out.println("Ignore");
                    flag = false;
                    break;
                }
            }
            if (flag) {
    
    
                System.out.println("Important!");
            }
        }
    }
}

有理数演算 (20)

2 つの有理数の場合、基本的な算術演算を実行すること、つまり、それらの和、差、積、
商を計算することがタスクとなります。

説明を入力してください:

Each input file contains one test case, which gives in one line the two rational numbers in the format "a1/b1 a2/b2". 
The numerators and the denominators are all in the range of long int. If there is a negative sign, it must appear only in 
front of the numerator. The denominators are guaranteed to be non-zero numbers.

出力の説明:

For each test case, print in 4 lines the sum, difference, product and quotient of the two rational numbers, respectively. The format of each 
line is "number1 operator number2 = result". Notice that all the rational numbers must be in their simplest form "k a/b", where k is 
the integer part, and a/b is the simplest fraction part. If the number is negative, it must be included in a pair of parentheses. If the 
denominator in the division is zero, output "Inf" as the result. It is guaranteed that all the output integers are in the range of long int.

入力

5/3 0/6

出力

1 2/3 + 0 = 1 2/3<br/>1 2/3 - 0 = 1 2/3<br/>1 2/3 * 0 = 0<br/>1 2/3 / 0 = Inf

【分析】

1. 出力には 4 行が含まれます: 2 つの分数の加算、減算、乗算、除算。
例:
a+ b = c
a - b = ca * b = ca /​​ b = c

2. 結果の各部分は最も単純な形式である必要があります。2/4
4===>1/2 は表示できません。最も単純な形式- 最大公約数で割るだけです

3. 負の数の場合は、負符号を出力する必要があります。

4. 分母が0の場合はInfを出力

5. 分子、分母ともにlong intの範囲内である。

例: - a/b + c/d = (a*d + b*c)/(b*d) 共通点を加算および減算して、2/3 + 2/5 = (
2*5 + 2*3)を取得します。 ) /(3*5)

——a/b - c/d = (a*d - b*c)/(b*d)
2/3 - 2/5 = (2*5 - 2*3)/(3*5)

——a/b * c/d = (a*c) / (b*d) 分子 x 分子、分母 x 分母
2/3 * 2/5 = (2*2) / (3*5)

——a/b / c/d = (a*d) / (b*c) の除算は、逆数の乗算と同じです
2/3 / 2/5 = (2*5) / (3*2) = 10/ 6 — >簡素化する

import java.util.*;

class Rational {
    
    
    private long numerator; // 分子
    private long denominator; // 分母
    private long integer; // 带分数的整数部分
    private boolean negative; // 负数
    private boolean isZero; // 分母为 0
    private long totalNumerator; // 参与运算的分子:带分数的整数部分 + 原来分子

    // 截取 分子部分
    protected static long parseNumerator(String s) {
    
    
        return Long.parseLong(s.substring(0, s.indexOf('/')));
    }

    // 截取 分母部分
    protected static long parseDenominator(String s) {
    
    
        return Long.parseLong(s.substring(s.indexOf('/') + 1, s.length()));
    }

    // 判断化简 分子 分母
    protected Rational(long n, long d) {
    
    
        // 在输入的时候分母永远不可能为0,但是经过计算之后分母可能会为0
        if (0 == d) {
    
    
            isZero = true;
            return;
        }
        // If there is a negative sign, it must appear only in front of the numerator.
        if (n < 0) {
    
    
            negative = true;
        }
        // 在输入的时候,分母永远不可能小于0,但是经过计算之后分母也可能会小于0
        if (d < 0) {
    
    
            negative = !negative;
        }
        // 如果输入是假分数,需要将其调整为真分数 --> 5 / 3 --> 1 2/3
        integer =  n / d;
        numerator = n - integer * d;
        denominator = Math.abs(d);
        // 如果分数不是最简的形式,需要将其约分为最简的形式,比如:10 / 15
        // 在分子和分母的基础之上分别处以分子和分母的最大公约数
        if (numerator > 1 || numerator < -1) {
    
    
            long gcd = calcGCD(Math.abs(numerator), denominator); // 用整数
            if (gcd > 0) {
    
     // 有最大公约数
                numerator /= gcd;
                denominator /= gcd;
            }
        }
        // 用于计算的分子 如果是假分数,化成真分数计算
        totalNumerator = numerator + integer * denominator;
    }

    // 最大公约数 辗转相除法
    private long calcGCD(long n1, long n2) {
    
    
        if (n2 == 0) {
    
    
            return n1;
        }
        return calcGCD(n2, n1 % n2);
    }

    // 计算
    protected Rational Add(Rational r) {
    
     // 通分
        long n = totalNumerator * r.denominator + r.totalNumerator * denominator; // 分子
        long d = denominator * r.denominator; // 分母
        return new Rational(n, d); // 结果同样是最简加假分式
    }

    protected Rational Sub(Rational r) {
    
     // 通分
        long n = totalNumerator * r.denominator - r.totalNumerator * denominator;
        long d = denominator * r.denominator;
        return new Rational(n, d);
    }

    protected Rational Mul(Rational r) {
    
    
        long n = totalNumerator * r.totalNumerator;
        long d = denominator * r.denominator;
        return new Rational(n, d);
    }

    protected Rational Div(Rational r) {
    
    
        long n = totalNumerator * r.denominator;
        long d = denominator * r.totalNumerator;
        return new Rational(n, d);
    }

    // 判断输出形式
    public String toString() {
    
    
        if (isZero) {
    
     // 分母为 0 输出 Inf
            return "Inf";
        }
        if (integer == 0 && numerator == 0) {
    
     // 结果为 0
            return "0";
        }
        StringBuilder stringBuilder = new StringBuilder();
        if (negative) {
    
     // 负数
            stringBuilder.append("(-");
        }
        // 输出 Rational:整数部分 + 分数部分
        // 整数部分
        if (0 != integer) {
    
    
            stringBuilder.append(Math.abs(integer));
            if (0 != numerator) {
    
     // 有分数 和整数之间有空格
                stringBuilder.append(" ");
            }
        }
        // 分数部分 可能没有
        if (0 != numerator) {
    
    
            stringBuilder.append(Math.abs(numerator) + "/" + denominator);
        }
        if (negative) {
    
    
            stringBuilder.append(")");
        }
        return new String(stringBuilder);
    }
}

public class Main {
    
    
    public static void main(String[] args) {
    
    
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNext()) {
    
    
            // 读取两个分数 分别截取出各自的 分子 和 分母
            String s = scanner.next(); //
            Rational r1 = new Rational(Rational.parseNumerator(s), Rational.parseDenominator(s));
            s = scanner.next(); //
            Rational r2 = new Rational(Rational.parseNumerator(s), Rational.parseDenominator(s));
            // 输出 两个分数 运算符 计算的结果
            // ——> 5/3   3/2
            // 1 2/3 + 1 1/2 = 3 1/6
            System.out.println(r1 + " + " + r2 + " = " + r1.Add(r2));
            System.out.println(r1 + " - " + r2 + " = " + r1.Sub(r2));
            System.out.println(r1 + " * " + r2 + " = " + r1.Mul(r2));
            System.out.println(r1 + " / " + r2 + " = " + r1.Div(r2));
        }
    }
}

事前事後

私たちは皆、バイナリ ツリーの事前順序、順序内、および順序後の走査についてよく知っています。データ構造クラスの一般的な問題は、順序内および事後走査が与えられた場合に、バイナリ ツリーの前順序走査を見つけることです。あるいは、in-order と pre-order が与えられた場合、事後探索を見つけることもできます。ただし、一般に、ツリーの前順序および後順序の走査が与えられた場合、その順序どおりの走査を決定することはできません。以下の 4 つのバイナリ ツリーについて考えてみましょう。

画像これらのツリーはすべて、同じ事前順序および事後探索を持ちます。この現象は二分木に限定されるものではなく、一般的な多分木にも同様に当てはまります。

説明を入力してください:

Input will consist of multiple problem instances. Each instance will consist of a line of the form m s1 s2, indicating that the trees are m-ary trees, s1 is the pre-order traversal and s2 is the post-order traversal.All traversal strings will consist of lowercase alphabetic characters. For all input instances, 1 <= m <= 20 and the length of s1 and s2 will be between 1 and 26 inclusive. If the length of s1 is k (which is the same as the length of s2, of course), the first k letters of the alphabet will be used in the strings. An input line of 0 will terminate the input.

出力の説明:

For each problem instance, you should output one line containing the number of possible trees which would result in the pre-order and post-order traversals for the instance. All output values will be within the range of a 32-bit signed integer. For each problem instance, you are guaranteed that there is at least one tree with the given pre-order and post-order traversals.

入力

2 abc cba
2 abc bca
10 abc bca
13 abejkcfghid jkebfghicda

出力

4
1
45
207352860

【分析】

テスト ケースの各セット: m s1s2
m はツリーが m 分ツリーであることを意味し、s1 は前順走査結果を意味し、s2 は順序内走査結果を意味します。s1 と s2 は同じ長さを持ち、小文字が含まれます。

1 つのテスト ケースは 1 行を占有し、最後のテスト ケースの後の行は 0 を出力します
: 各ユース ケースは可能なすべてのツリーの数を入力し、1 行を出力します。結果は unsigned long を超えてはなりません

ここに画像の説明を挿入します

**——分离根节点有多少颗子树:**

ここに画像の説明を挿入します

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

// 保存子树的前序 后序 遍历结果
class SubTree {
    
    
    String pre;
    String post;
    public SubTree(String pre, String post) {
    
    
        this.pre = pre;
        this.post = post;
    }
}

public class Main {
    
    
    // 计算 n 的阶乘
    private static long fac(int n) {
    
    
        long f = 1;
        for (int i = 1; i <= n; i++) {
    
    
            f *= i;
        }
        return f;
    }

    // 计算组合
    private static long calcCom(int n, int m) {
    
    
        m = m < (n - m) ? m : (n - m); // C(n, m) = C(n, n-m)
        long r = 1;
        for (int i = n; i >= n - m + 1; i--) {
    
    
            r *= i;
        }
        return r / fac(m);
    }

    // 分离根节点有多少颗子树
    private static List<SubTree> calcSubTree(String pre, String post) {
    
    
        int subRootPreInx = 1; // 子树的根在前序遍历结果中的位置   根--->子树1--->子树2--->...--->子树n
        int postFirst = 0; // 后序遍历 : 子树1-->子树2-->...--->子树n-->根节点
        List<SubTree> list = new ArrayList<>();
        while (subRootPreInx < pre.length()) {
    
    
            char rootSub = pre.charAt(subRootPreInx); // 确认该颗子树的根节点 从前序遍历中找根
            int subRootPostInx = post.indexOf(rootSub); // 从后序遍历中找根的位置
            int subTreeNodeCount = subRootPostInx - postFirst + 1; // 该颗子树中总共有多少个节点
            SubTree subTree = new SubTree(
                    pre.substring(subRootPreInx, subRootPreInx + subTreeNodeCount),
                    post.substring(postFirst, postFirst + subTreeNodeCount)
            ); // 从前序遍历和后序遍历结果中分离出该棵子树的 前序和后序遍历结果
            list.add(subTree); // 保存 子树的 前序和后序遍历结果
            subRootPreInx += subTreeNodeCount; // 分离下一颗子树
            postFirst += subTreeNodeCount;
        }
        return list;
    }

    private static long calcPossibilitiesOfTree(int n, String pre, String post) {
    
    
        if (pre.isEmpty() || pre.length() == 1) {
    
     // 没有节点 或 只有一个节点
            return 1;
        }
        List<SubTree> subTree = calcSubTree(pre, post); // 分离根节点有多少颗子树
        long result = calcCom(n, subTree.size()); // 根节点子树 的可能性的 组合 结果
        for (SubTree e : subTree) {
    
     // 递归计算 根的子树 分别有多少种可能性
            result *= calcPossibilitiesOfTree(n, e.pre, e.post);
        }
        return result;
    }

    public static void main(String[] args) {
    
    
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNext()) {
    
    
            int n = scanner.nextInt();
            if (n == 0) {
    
     // An input line of 0 will terminate the input.
                break;
            }
            String pre = scanner.next();
            String post = scanner.next();
            long ret = calcPossibilitiesOfTree(n, pre, post);
            System.out.println(ret);
        }
    }
}

おすすめ

転載: blog.csdn.net/qq_56884023/article/details/125114930