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

1. 選択

単一の選択

長さ M の N 個の順序付けされたリンク リストをマージします。マージされたリンク リストも順序付けされたままになります。時間計算量は ()?

  • A O(N * M * logN)
  • ボ(N*M)
  • CO(N)
  • ど(男)

1. 長さ N の最大/最小ヒープを作成します。これらの N 個のリンク リストの最初の要素を取り出して、最小のヒープを作成します。時間計算量: O(N)

2. 最小ヒープから要素(ヒープの先頭)を順番に取り出しますが、このときヒープの先頭は現在のセットの最小値となり、リンクリストの他の要素をヒープに入れます。ヒープ調整の時間計算量: O(siftDown - N*M*logN)、ヒープに追加する必要がある要素の総数、O(N*M*logN)

3. 合計: ヒープの構築 + ヒープの継続的な調整 (ヒープの最上位要素を継続的に取り出す) O(N) + O(N*M*logN)、最高位: O(N*M*logN)

サイズが MAX の循環キューでは、f は先頭要素の現在位置、r は現在の末尾要素の位置 (最後の要素の位置) です。その後、任意の時点で、キューは

  • RF
  • B (r-f+MAX+1)%MAX
  • C r-f+1
  • D(r-f+MAX)%MAX

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

HASH 関数の競合処理方法には、次のいずれも含まれません。

  • オープンなアドレス指定方法
  • Bチェーンアドレス方式
  • C挿入ソート
  • D 公共越流区域法

小さなルート ヒープは 8,15,10,21,34,16,12 であることがわかっています。キーワード 8 を削除した後、ヒープを再構築する必要があります。このプロセス中に、キーワード間の比較の数は () 回になります。

  • A1
  • B2
  • C3 _
  • D4

ヒープの最上部はヒープの最後の要素と交換され、小さなルート ヒープまで下方に調整されます。

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

以下の選択肢のうち、クイックソートの2番目のソート結果にならないものは()です。

  • A 2、3、5、4、6、7、9
  • B 2,7,5,6,4,3,9
  • C 3,2,5,4,7,6,9
  • D 4,2,3,5,7,6,9

クイックローを実行するたびに、キャリブレーションポイントが最終位置になければなりません。2 つのクイック キューの後、少なくとも 2 つの要素が最終位置に到達しました。

A:2 3 9。B:2 9。C:9。D:5 9

ヒープソートの平均実行時間の複雑さと必要な追加ストレージスペースの複雑さは次のとおりです ()

  • A O(N2)和O(1)
  • B O(Nlog2N)和O(1)
  • CO(Nlog2N) と O(N)
  • D O(N2)和O(N)

インプレースヒープソート

JVM メモリに関する次の記述のうち、間違っているものはどれですか?

  • A プログラム カウンタは比較的小さいメモリ領域で、現在のスレッドによって実行されたバイトコードのどの行が実行されたかを示すために使用され、スレッド分離されています。
  • B Java メソッド実行メモリ モデルは、ローカル変数、オペランド スタック、ダイナミック リンク、メソッド出口、その他の情報を保存するために使用され、スレッド分離されています。
  • Cメソッド領域は、クラス情報、定数、静的変数、JVM によってロードされるジャストインタイム コンパイラによってコンパイルされたコードなどのデータを格納するために使用され、スレッド分離されています。
  • D 原則として、すべてのオブジェクトはヒープ領域にメモリを割り当て、スレッド間で共有されます。

メソッド領域はスレッド間で共有されます

次のプログラムセグメントの出力結果は次のとおりです: ( )

public void complicatedexpression_r(){
     
     
     int x=20, y=30;
     boolean b;
     b = x > 50 && y > 60 || x > 50 && y < -60 || x < -50 && y > 60 || x < -50 && y < -60;
     System.out.println(b);
 }
  • Bfalse _
  • C1
  • D0

入力ストリームは、ファイル、標準入力、またはその他の外部入力デバイスからメモリにデータを読み込みます。Java では、入力ストリームは抽象クラス () とそのサブクラスに対応します。

  • java.io.InputStream
  • B java.io.OutputStream
  • C java.os.InputStream
  • D java.os.OutputStream

プログラムのコンパイルに関する次の記述のうち、正しいものはどれですか ()

  • Java 言語はコンパイル言語であり、Java プログラムをバイナリ機械命令にコンパイルし、直接実行します。
  • B Java によってコンパイルされたターゲット ファイルは、特定のオペレーティング システムに関連しています。
  • C Java は実行時にのみ命令を変換します
  • D java によってコンパイルされたターゲット ファイルは、任意の JVM 上で実行できます。

Java は半コンパイルおよび半インタープリタ言語です。

class はオペレーティング システムに依存しない JVM 指向のバイナリ ファイルです

1. コンパイル: javac、*.java -> *.class。2. 実行: javaJVM は実際にクラス ファイルをシステム操作用のマシン コードに変換します。

JVMにもバージョンがあり、クラスファイルJDK8やJDK11は動作しません。

現在のスレッドの実行を終了できる状況は次のどれですか?

  • A 高優先スレッドが準備完了状態になったとき
  • B は例外をスローします
  • C スレッドが sleep() メソッドを呼び出すとき
  • D新規スレッド作成時

スレッドの終了:
1. スレッドのタスクが完了する(正常終了)
2. スレッドの実行中に例外が発生する(異常終了)

public static void main(String args[]) {
    
    
        Thread t=new Thread(){
    
    
            public void run(){
    
    
                dianping();
            }
        };
        t.run();
        System.out.print("dazhong"); }
    static void dianping(){
    
    
        System.out.print("dianping");
    }
  • 大中点評
  • B 点平大中
  • C a と b は両方とも可能です
  • D点平ループ出力、dazhongが途中で混合されます

この質問では、スレッド t は起動されていませんが、 run() メソッドが呼び出されています。新しいスレッドを起動せずに、直接 Run() メソッドが呼び出されます。これは、通常のメソッドを呼び出すことと同等です。プログラム内で実行されているスレッドはまだ 1 つだけであるため、プログラムは順番に実行されます。つまり、run() が最初に実行され、run() メソッドが dianping() メソッドを呼び出して「dianping」を出力します。プログラムは下方向に実行を続け、「dazhong」を出力します。この質問の t スレッドが start() メソッドを呼び出すと、オプション C が表示されます。結論から言うと正解はBです。

パブリック インターフェイス IService {String NAME="default";}

デフォルトの同等の型はどの項目を表しますか?

  • パブリック文字列 NAME="default";
  • B public static String NAME="デフォルト";
  • C public static Final String NAME=“default”;
  • D プライベート文字列 NAME="デフォルト";

インターフェイス内の変数はすべてグローバル定数 public static Final

次のクラス定義があります。

abstract class Animal{
     
     
 abstract void say();
}
public class Cat extends Animal{
     
     
 public Cat(){
     
     
     System.out.printf("I am a cat");
 }
 public static void main(String[] args) {
     
     
     Cat cat=new Cat();
 }
}

実行後:

  • AIは猫です
  • B Animal はコンパイルできますが、Cat はコンパイルできません。
  • C Animal はコンパイルできませんが、Cat はコンパイルできます。
  • Dコンパイルは通るが出力結果が無い

抽象クラスのサブクラスは、すべての抽象メソッドをオーバーライドする必要があります (サブクラスは抽象クラスではありません)。

Java におけるメソッドのオーバーロードとメソッドのオーバーライドに関する次の説明のうち、正しいものはどれですか?

  • メソッドのオーバーロードとメソッドのオーバーライドは同じ機能を実装します
  • B メソッドのオーバーロードが親子関係にあり、メソッドのオーバーライドが同じクラス内にある
  • Cメソッドのオーバーロードの戻り値の型は一貫しており、パラメータの項目は異なっていなければなりません
  • D メソッドのオーバーライドの戻り値の型は、同じか互換性がある必要があります。
// 向上转型类的返回值可以
class A {
    
    
    A test() {
    
    
        return this;
	}
}

class B extends A {
    
    
    B test() {
    
    
		return this;s
    }
}

メモリのリサイクルに関する次の記述のうち、正しいものはどれですか?( )

  • A プログラマはメモリを解放するためにスレッドを作成する必要があります。
  • B メモリリサイクルプログラムは、不要なメモリを解放する役割を果たします**
  • C メモリ リクレーマにより、プログラマはメモリを直接解放できます。
  • D メモリ リサイクル プログラムは、指定した時間にメモリ オブジェクトを解放できます

JVM ガベージ コレクションは JVM 自体によって実行されます

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

  • 仮パラメータはフィールド修飾子によって変更できます
  • B 仮パラメータをオブジェクトにすることはできません
  • C の仮パラメータは、メソッドの呼び出し時に実際に渡されるパラメータです。
  • D 仮パラメータはローカル変数として扱うことができます

A: フィールド修飾子: アクセス権 public など。C: 実際のパラメータ。D: 仮パラメータはローカル変数として扱うことができます

Java 7 では、次の記述のうち正しいものはどれですか。

  • ConcurrentHashMap は synchronized キーワードを使用してスレッドの安全性を確保します
  • B HashMap は Collection インターフェースを実装します
  • C の Arrays.asList メソッドは java.util.ArrayList オブジェクトを返します
  • D SimpleDateFormat オブジェクトはスレッドセーフではありません

答え: ロックします。B: Collection インターフェイスは線形テーブルの最上位インターフェイスであり、HashMap は Map インターフェイスを実装します。C: リストインターフェイスオブジェクト

public static <T> List<T> asList(T... a) {
    
    
    return new ArrayList<>(a);
}

次のプログラム セグメントに関する正しい記述は次のとおりです: ()

String s1="abc"+"def";//1
String s2=new String(s1);//2
if(s1.equals(s2))//3
System.out.println(".equals succeeded");//4
if(s1==s2)//5
System.out.println("==succeeded");//6
  • A 4行目と6行目は実行されません。
  • B 行 6 は実行されますが、行 4 は実行されません。
  • C 行 4 は実行されますが、行 6 は実行されません。
  • D 行 4 と行 6 が実行されます

文字列オブジェクトが等しいかどうかを比較するには、内容を比較するのに equals を使用し、アドレスを比較するのに == を使用します。

コマンド モードで次のコードを実行した結果は () になります。

public class f{
     
     
	public static void main(String[] args){
     
     
		String foo1 = args[1];
		String foo2 = args[2];
		String foo3 = args[3];
	}
}

コマンド: Java fabc

  • プログラムのコンパイルエラー
  • B abc
  • Cプログラム実行エラー
  • D f

コンパイルコマンド:javac ソースファイル名.java *.java -> *.class
実行コマンド:java main クラス名 渡すパラメータ(main に渡す引数内)
java fabc —— args{a, b, c} —— [ 0-2】

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

  • A クラスメソッド内で使用して、このクラスのクラスメソッドを呼び出すことができます。
  • B は、クラス メソッド内でこのクラスのクラス メソッドを直接呼び出すことができます。
  • C. クラスメソッドでは、このクラスのクラスメソッドのみを呼び出すことができます。
  • D インスタンス メソッドはクラス メソッド内から呼び出してはなりません

A: これは現在のオブジェクト参照を表すため、静的フィールドを呼び出すことはできません。B: 静的メソッドには、直接使用できるオブジェクトがありません。CD: オブジェクトがクラス メソッドで作成された場合でも、そのオブジェクトを通じてインスタンス メソッドを呼び出すことができます。

class Test {
    
    
	void func() {
    
    };
    static void test() {
    
    
		Test test = new Test();
        test.func();
    }
}

次のクラスの説明が知られています。

public class Test{
     
     
	private float f=1.0f;
	int m=12;
	static int n=1;
	public static void main(String args[]){
     
     
		Test t=new Test();
	}
}

次の用法のうち正しいものはどれですか ()

  • A tf = 1.0
  • Bこれ.n
  • Cテスト.m
  • Dテスト.n

次のコードがあります。

class A{
     
     
	public A(String str){
     
     
	}
}
public class Test{
     
     
	public static void main(String[] args) {
     
     
		A classa=new A("he");
		A classb=new A("he");
		System.out.println(classa==classb);
	}
}

出力結果は次のとおりです。

  • 偽に
  • B 本当
  • Cエラー
  • D 上記の選択肢はどれも正しくありません

== は 2 つの参照のアドレスを比較します。Classa と classb は両方とも新しいため、アドレスは等しくなくてはなりません。

Java クラスのロード プロセスの一部ではないものは次のうちどれですか?

  • A は java.lang.Class オブジェクトを生成します
  • B int型のオブジェクトメンバ変数にはデフォルト値が割り当てられます
  • C 静的ブロック コードを実行する
  • Dクラスメソッド分析

B: メンバ変数は初期化されず、静的変数のみが初期化されます。クラスロード後のオブジェクト生成時に実行され、クラスロードプロセスには属しません。

Java () でスレッドを作成および開始できるのは次のうちどれですか?

public class MyRunnable implements Runnable {
     
     
	public void run() {
     
     
		//some code here
	}
}
  • 新しい Runnable(MyRunnable).start()
  • B 新しい Thread(MyRunnable).run()
  • C new Thread(new MyRunnable()).start()
  • D new MyRunnable().start()

スレッドの作成と開始のプロセスは、スレッドの定義 -> スレッドのインスタンス化 -> スレッドの開始です。スレッドを定義するには 2 つの方法があり、1 つは java.lang.Thread クラスを継承する方法、もう 1 つは java.lang.Runnable インターフェースを実装する方法です。スレッドをインスタンス化するこれら 2 つの方法の違いは、Thread クラスを継承する場合、新しいオブジェクトを直接作成できることです。それが Runnable インターフェイスを実装するクラスの場合は、Thread コンストラクターを使用する必要があります。 Thread(Runnable target ) Thread(Runnable target, String name) Thread(ThreadGroup グループ, Runnable target) Thread(ThreadGroup グループ, Runnable target, String name) Thread(ThreadGroup グループ, Runnable target, String name, long stackSize) したがって、スレッドのインスタンス化でエラーが発生します2 つのオプション A と D。オプション B の新しい Runnable (MyRunnable) の MyRunnable がインスタンス化されていないため、コンパイルが失敗します。後で run() または start() が呼び出されるかどうかに関係なく、このオプションは間違っています。

TCPポート 9000をリッスンしたい場合、サーバー側でソケットをどのように作成すればよいでしょうか?

  • 新しい Socket(“localhost”,9000);
  • B 新しいサーバーソケット(9000);
  • C 新しいソケット(9000);

サーバーは ServerSocket(int port) を使用します。これはデフォルトでローカルに指定されたポート番号を使用して TCP ポートをリッスンし、
クライアントは Socket を使用してサーバーに接続します Socket(lP, port)

次のクラス宣言のうち正しいものはどれですか?

  • 抽象最終クラス HI{}

  • B 抽象プライベート move(){}

  • C 保護されたプライベート番号。

  • D パブリック抽象クラス Car{}

Java インターフェースの修飾子は () です。

  • プライベート
  • B保護
  • C決勝
  • D アブストラクト

タイトルはインターフェイス定義で直接使用される修飾子を参照しており、インターフェイスの権限はすべてパブリックです。

jre がプログラムの実行が終了したかどうかを判断する基準は () です。

  • A すべてのフォアグラウンド スレッドが実行されました
  • B すべてのバックグラウンド スレッドが実行されている
  • C すべてのスレッドが実行された
  • Dは上記とは関係ありません

JRE: Java ランタイム環境
JDK: JRE を含む Java 開発キット
Java プロセスがプログラムが完全に実行されたとみなしたとき: すべてのフォアグラウンド スレッド (ユーザー スレッド) が実行され、手動で
バックグラウンド スレッドとして設定されました:setDameon(true)
通常、作成するスレッドは次のとおりです。フォアグラウンド スレッド。バックグラウンド スレッド: JVM ガベージ コレクション スレッド

int i=5;
int s=(i++)+(++i)+(i–)+(–i);
s=( )//s の値は何ですか?

  • A28
  • B25
  • C21
  • D26
  • E24
  • F23

5 7 7 5

以下は Object クラスのメソッドではありません。

  • ハッシュコード()
  • やっとB()
  • C 待機()
  • D toString()

finalize()スレッドリソースを解放するために使用されるオブジェクトクラスのメソッドです。

jdk1.6 ガベージ コレクターに属さないものは次のうちどれですか?

  • シリアルコレクター
  • Bパー新規コレクター
  • C CMSコレクター
  • D G1コレクター

JDK7以降のバージョン

instanceof 演算子を使用すると、オブジェクトが次のとおりであるかどうかを判断できます。

  • クラスのインスタンス
  • B 指定されたインターフェイスを実装するクラスのインスタンス
  • C すべて正しい
  • D サブクラスのインスタンス

クラスのインスタンス化に関するステートメントは次のうちどれですか?

  • varName ClassName=new varName();
  • B クラス名 varName=新しいクラス名(新しいクラス名);
  • C クラス名 varName=クラス名();
  • D クラス名 varName=新しいクラス名();

クラス名参照名 = new class();

次のコードをコンパイルして実行すると、次のオプションのうちどれが発生しますか?

public class Pvf{
     
     
	static boolean Paddy;
	public static void main(String args[]){
     
     
		System.out.println(Paddy);
	}
}
  • コンパイル時エラー
  • B は正常にコンパイルされ、false が出力されます。
  • C は正常にコンパイルされ、結果 true が出力されます。
  • D は正常にコンパイルされ、null 結果が出力されます

クラスで宣言された変数にはデフォルトの初期値がありますが、メソッドで宣言された変数にはデフォルトの初期値がないため、定義時に初期化する必要があります。そうしないと、変数にアクセスするときにエラーが発生します。この質問では、Paddy は静的メンバー変数なので、初期値としてブール型の false が得られます。

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

  • インスタンスメソッドはスーパークラスのインスタンスメソッドを直接呼び出すことができます。
  • Bインスタンスメソッドはスーパークラスのクラスメソッドを直接呼び出すことができます
  • C のインスタンス メソッドはサブクラスのインスタンス メソッドを直接呼び出すことができます
  • Dインスタンス メソッドはこのクラスのインスタンス メソッドを直接呼び出すことができます

A: スーパー()。B: クラス名。C: サブクラスオブジェクト

HashSet サブクラスは、() メソッドに依存して重複要素を区別します。

  • toString(),equals()
  • B clone(),equals()
  • C のhashCode()、equals()
  • D getClass()、clone()

まずオブジェクト ハッシュコード メソッドを呼び出してオブジェクトを配列添字にマップし、次に equlas を使用して要素の内容が同じかどうかを判断します。

次のコードをコンパイルして実行するとどうなりますか?

public class TestDemo{
     
     
 private int count;
 public static void main(String[] args) {
     
     
     TestDemo test=new TestDemo(88);
     System.out.println(test.count);
 }
 TestDemo(int a) {
     
     
     count=a;
 }
}
  • A は正常にコンパイルおよび実行され、出力結果は 88 になります。
  • B コンパイル時エラー。カウント変数はプライベート変数として定義されています。
  • C コンパイル時エラー、System.out.println メソッドの呼び出し時にテストが初期化されない
  • D コンパイルおよび実行時に出力がありません。

private はクラス内で使用でき、count はメンバー変数であり、オブジェクトを通じてアクセスされます。

次のプログラムを実行した結果は次のようになります。

class X{
     
     
 Y y=new Y();
 public X(){
     
     
     System.out.print("X");
 }
}
class Y{
     
     
 public Y(){
     
     
     System.out.print("Y");
 }
}
public class Z extends X{
     
     
 Y y=new Y();
 public Z(){
     
     
     System.out.print("Z");
 }
 public static void main(String[] args) {
     
     
     new Z();
 }
}
  • ジクス
  • B ジクシー
  • C YXYZ
  • DXYZX

親クラスの静的メンバ変数と静的コードブロックを初期化する; サブクラスの静的メンバ変数と静的コードブロックを初期化する; 3. 親クラスの通常のメンバ変数とコードブロックを初期化して、親クラスの構築メソッドを実行する。 4. 初期化 サブクラスの通常メンバ変数とコードブロックを初期化し、サブクラスの構築メソッドを実行する具体的な処理は次のとおりです: (1) 親クラスの通常メンバ変数とコードブロックを初期化し、Y を実行y=new Y(); 出力 Y (2) 次に、親クラスの構築メソッドを実行します; 出力 C

  • 継承する場合は、まず親クラスのコンストラクターを呼び出します。
  • クラス内のメンバー変数の初期化操作はすべてコンストラクター メソッドで実行されます。

そのようなプログラムがあります:

public class Test{
     
     
 public String name="abc";
 public static void main(String[] args){
     
     
     Test test=new Test();
     Test testB=new Test();
     System.out.println(test.equals(testB)+","+test.name.equals(testB.name));
 }
}

上記のプログラムを実行した結果はどうなりますか()

  • 本当の、本当の
  • B true、false
  • C 偽、真
  • D 偽、偽

Object が提供する equals メソッドは、デフォルトでオブジェクトのアドレスが同じかどうかを比較します。文字列は、値が等しいかどうかを比較するために、equals メソッドをオーバーライドします。

次の簡単な例を考えて、リフレクションがどのように機能するかを見てみましょう。

import java.lang.reflect.*;
public class DumpMethods{
     
     
 public static void main(String[] args) {
     
     
     try {
     
     
         Class c=Class.forName(args[0]);
         Method m[]=c.getDeclaredMethods();
         for (int i = 0; i < m.length; i++) {
     
     
             System.out.println(m[i].toString());
         }
     } catch (Throwable e) {
     
     
         System.err.println(e);
     }
 }
}

「c.getDeclaredMethods」の機能は次のとおりです。

  • A クラスのパブリックメソッドオブジェクトを取得します。
  • B クラスのすべてのパブリック メソッドの名前を取得します。
  • C クラスのすべてのメソッド オブジェクトを取得する
  • D 上記の選択肢はどれも正しくありません

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

Java の文字型は Unicode エンコーディング スキームを使用しており、各 Unicode コードは () ビットを占有します。
A 8
B 16
C 32
D 64

int 型変数 x に対する次のマルチスレッド操作のうち、同期が必要ないものはどれですか ()
A ++x
B x=y
C x++
D x=1

B: x の代入は、非アトミックな変数に依存します。D: 直接代入操作はアトミック操作です

次の 4 つのステートメントがあります: ()

Integer i01=59; // 自动装箱
int i02=59;
Integer i03=Integer.valueOf(59); // 装箱
Integer i04=new Integer(59); // 在堆上 new 了一个新对象

次の出力結果は false です:
A System.out.println(i01==i02); // i01 を自動的にアンボックス化し、整数に復元します
B System.out.println(i01==i03); // true
C System.out.println(i01==i03); // true。 out.println(i03==i04); // new があれば新しいスペースがあり、i03 と i04 のアドレスは等しくありません
System.out.println(i02==i04); // 自動的にアンボックス化します、i04 は int に復元されます

オプション A および D では、ラッパー クラスが基本データ型と比較される場合、ラッパー クラスは比較前に自動的にボックス化解除され、基本型になります。つまり、整数 i01 はボックス化されて int 型になり、i02 と比較されます。したがって、System.out.println(i01==i02); 出力は true になります。オプション B、ラップされたデータ クラスは値を直接割り当て、対応する valueOf() メソッドがデフォルトで呼び出されます。Integer i03=Integer.valueOf(59); は Integer i01=59; valueOf() と同等で、-128 ~ 127 の範囲の整数を演算します。再度参照する場合はキャッシュから直接検索し、-128~127以外の整数を演算する場合は毎回新しいオブジェクトを作成する必要があります。つまり、-128 ~ 127 の整数を作成した場合、valueOf を使用して再度作成すると、new キーワードは使用されず、キャッシュされたオブジェクトが使用されます。したがって、 System.out.println(i01==i03); は true を出力します。オプション C のラッパー クラスは、基本データ型の参照型です。i04 の定義では new キーワードが使用されており、値 59 の Integer オブジェクトを配置するための新しいメモリが開かれます。すると、アドレスの異なる2つの参照型変数に対する==判定の結果は当然偽となります。選択肢Cに答えます。

// 原码:
public static Integer valueOf(int i) {
    
    
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }

ユニプロセッサ システムでは、12 個のプロセスが同時に存在する場合、レディ キュー内のプロセスの最大数は () になります。

A1

B9

C10

D11

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

  • スレッドの同期方法には、クリティカル セクション、ミューテックス、セマフォなどの使用が含まれます。
  • B 同時に単純型のグローバル変数に書き込む場合、2 つのスレッドが相互排他的である必要もあります。
  • Cでリエントラント関数を実装する場合、自動変数を保護するためにミューテックスも使用する必要があります。
  • D 再入可能関数は非再入可能関数を呼び出すことはできません

クリティカル セクション: 複数のスレッドのシリアル化を通じてパブリック リソースまたはコードにアクセスします。高速であり、データ アクセスの制御に適しています。(クリティカル セクションは、共有リソースを操作するコードの一部と考えることができます)
Mutex: 共有リソースへの個別のアクセスを調整するように設計されています。セマフォ: 限られた数のユーザーでリソースを制御するために設計されています。|
イベント: いくつかのイベントが発生したことをスレッドに通知するために使用され、それによって後続のタスクが開始されます。

リエントラント関数:
主にマルチタスク環境で使用されます。リエントラント関数とは、単に中断できる関数です。つまり、関数は実行中にいつでも中断でき、実行のために OS のスケジューリングに転送できます。コードは存在しますが、制御を返すときにエラーは発生しません; 非
リエントラント関数:
グローバル変数領域、割り込みベクタ テーブルなどの一部のシステム リソースが使用されるため、割り込みが発生すると問題が発生する可能性があります。このクラス関数は実行できません。マルチタスク環境。
自動変数:
定義時に作成されるローカル スコープ変数。関数が戻ると、システムはスペースを再利用します。スペースはスレッドにとってプライベートなものです。

システムデッドロックの考えられる原因は次のとおりです。

  • プロセスの無限ループ
  • Bリソースループ待機中
  • C プログラムのメモリ アクセスが範囲外です
  • D プロセスがリソースを解放する

整数 0x12345678、ビジェンディアンでのメモリのソート順序は ( )

  • 12 34 56 78
  • B 78 56 34 12
  • C 87 65 43 21
  • D 21 43 65 87

bigendian ビッグ エンディアン モード、littleenddian リトル エンディアン モード

C を使用して 1G バイトの文字配列を単語「A」まで設定すると、一般的な現代の PC では最も近い CPU 時間がかかります ()

  • 0.001秒
  • B 1秒
  • C 100秒
  • D 2時間

単位間の変換規則は次のとおりです。

1GB = 1024MB
1MB = 1024KB

1KB = 1024B

1B = 8bits
, so 1GB = 1,073,741,824B.
ステートメントの実行には約 1ns かかります。これは 1/1,00o,000,000 秒 (10^9) です。1B が割り当てられるたびに、ステートメントを実行する必要があるため、1G の場合、約 1 秒です。 10^9 * 1,073,741,824

通常のコンピューターの場合、次のイベントの時間のかかる順序は、小さいものから大きいものまで ____ です。

A. 1KB メモリ データを読み取る B. ハードディスクから 1KB データを連続的に読み取る C. L2 キャッシュを 1 回読み取る D. 1 回のディスク シーク

  • AC、A、D、B
  • BC、D、A、B
  • CD、C、A、B
  • DD、A、C、B

キャッシュはレベル 2 キャッシュ (二次キャッシュを意味します) であり、データはキャッシュを通じて CPU と直接やり取りされます。これが最も高速かつ直接的です。

2回目のメモリ読み出し時、CPUキャッシュ経由でデータを検索したところ、キャッシュにデータが存在しないことが判明し、このときメモリ内を検索する必要があるが、メモリの転送速度が遅いキャッシュほど高速ではないため、メモリの読み取りにかかる時間はキャッシュよりも長くなります。

3 番目は、ハードディスクから 1kb を連続して読み取ります。これは、ハードディスクのデータを読み取ることを意味します。ハードディスクのデータの読み取りにかかる時間は、主にシーク時間データ転送時間回転時間で構成されます。したがって、ディスクのシーク時間は明らかに短くなります。合計シーケンシャル読み取り時間よりも長くなります。

ページング仮想ストレージ管理システムでは、ページのサイズと発生する可能性のあるページフォルト中断の数 ( )

  • A は次のように正比例します。
  • Bはに反比例します
  • C 無関係
  • Dは固定値となる

ページ仮想ストレージ システム:ジョブ情報(メモリ上で操作されるデータ情報を指します) のコピーをディスクなどの補助記憶装置に保存します。ジョブの実行がスケジュールされると、ジョブのすべてのプログラムとデータが保存されます
メイン メモリにロードされず、すぐに使用されるページジョブ情報の少なくとも最初のページはメイン メモリにロードされる必要があり、実行中にメイン メモリにないページがアクセスされると、それらのページはロードされません。動的にロードされます。

より一般的に使用されるページング仮想ストレージ管理はデマンド ページングです特定の命令またはデータを実行する必要があるが、それらが主記憶にないことが判明した場合、ページフォールト割り込みが生成され、システムは二次記憶から起動されます。命令またはデータが配置されているページがメモリにロードされます。

メモリに入力されたページの内容は変わりませんしたがって、ページング仮想ストレージ管理システムでは、ページのサイズは、発生する可能性のあるページ フォールト中断の数とはほとんど関係がありません。

子プロセスと親プロセスについて正しいのはどれですか? ()

  • A 親プロセスは複数の子プロセスを作成でき、子プロセスは複数の親プロセスに従属することができます。
  • 親プロセス B がキャンセルされると、それに応じて子プロセスもすべてキャンセルされます。
  • C 子プロセスが取り消されると、その依存関係にある親プロセスも取り消されます。
  • D プロセスには親プロセスまたは子プロセスを含めることはできません

A: 親プロセスは複数の子プロセスを作成できますが、子プロセスは 1 つの親プロセスにのみ属します
B: 親プロセスが先に終了し、子プロセスがまだ終了していない場合、子プロセスは init プロセスに委ねられます。子プロセスは init プロセスに委託され、それらのステータス収集を完了します。このとき、子プロセスの親プロセスは init プロセス ((プロセス番号 1) です。init プロセスには親プロセスがありません。
C: 子プロセスが終了し、親プロセスは引き続き実行できます
。 D: init プロセスには親プロセスがないため、プロセスは子プロセスを作成する必要はありません。

スレッドとプロセスに関しては、次の記述が正しいです ()

  • A プロセスの終了は、スレッドの終了よりも時間がかかりません。
  • B プロセスの切り替えは、同じプロセス内のスレッドの切り替えよりも時間がかかりません
  • C スレッドにより、異なるエグゼキュータ間の通信効率が向上します
  • D プロセスとスレッドは、リソースの割り当てとスケジューリングの基本単位です。

プロセスの作成、切り替え、終了、および時間のかかる/消費するリソースはすべて、スレッドのリソースよりも高くなります。ABをHighに変更、Dはプロセス

プロセスのスケジューリング中に、次のプロセス状態の変化のうち、発生することが不可能なものはどれですか? ()

  • ブロック保留中 -> ブロック
  • B 準備完了待ち -> 準備完了
  • C準備完了保留中 -> ブロック保留中
  • Dブロッキングサスペンション→レディサスペンション

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

実行中のオペレーティング システム プログラムは () 内に配置する必要があります。

  • レジスター内
  • メインメモリ内のB
  • C補助記憶装置

実行中のオペレーティング システム プログラムは、メイン メモリ内にあるプロセスを参照します。

レジスタ: 容量が限られており、CPU がコードを実行するために必要なデータのみがロードされます (メイン メモリからレジスタにロードされます)。

補助ストレージ: プロセスが一時停止されると、プロセスは補助ストレージに保存されます。

システム メモリにディスク バッファを設定する主な目的は () です。

  • A ディスク I/O の数を減らす
  • B 平均シーク時間を短縮する
  • C ディスクデータの信頼性の向上
  • D デバイスの独立性を実現する

ディスクバッファにはディスクとディスクバッファがあります

CPU の実行速度はディスク IO 速度よりもはるかに高速であるため、
効率を向上させるために、ディスク キャッシュを使用して、頻繁にアクセスされるディスク データの IO 速度を上げることができます。

B はシーク時間は短縮しませんが、シーク数は減少します。

以下のオプションのうち、プロセスを実行状態から準備完了状態に遷移させるイベントは()です。

  • A は P(wait) 操作を実行します
  • B メモリの申請に失敗しました
  • C I/Oデバイスの起動
  • Dは優先度の高いプロセスによってプリエンプトされます

A:プロセス通信の方式の一つ、シグナル:p(ウェイト)セマフォ-1、v(シグナル)セマフォ+1。セマフォに従って、それが正の数であれば実行を続行できます

B: オペレーティング システムのカーネルがプロセスに通知し、プロセスが実行方法を決定します。通常はエラーが報告されます。

次のステートメントのうち、オペレーティング システムの主要な機能ではないものはどれですか? ()

  • プロセッサ管理
  • B メモリ管理
  • C デバイス管理とファイル管理
  • Dポータブル

プロセッサー管理: プロセス管理

最新のオペレーティング システムでバッファリング テクノロジを使用する主な目的は () です。

  • A ユーザープログラミング環境の改善
  • B CPUの処理速度を上げる
  • C CPU とデバイス間の並列度を高める
  • D デバイスの独立性を実現する

CPU の実行速度はディスク IO 速度よりもはるかに速いため、途中にバッファが追加されます。CPU はバッファへのデータの読み取りと書き込みを同時に行うことができ、ディスクもバッファへのデータの読み取りと書き込みを行うことができます。

プロセスとプログラムの本質的な違いは () です。

  • A 前者は動的、後者は静的です。
  • B 前者はメモリに保存され、後者は外部メモリに保存されます
  • C 前者は 1 つのファイル内にあり、後者は複数のファイル内にある
  • D 前者は CPU をタイムシェアリングで使用し、後者は CPU を独占します

プログラムは、外部メモリ内の静的な実行可能ファイルです。プロセスが実行中の場合はメモリ内にあり、一時停止中の場合は外部ストレージ内にあります。D: プログラムは実行されていません。静的実行ファイルです。記述が間違っています。

プロセスのディスク読み取り操作が完了した後、オペレーティング システムがプロセスに対して行う必要があることは ()

  • A プロセスステータスを準備完了状態に変更します。
  • B プロセスの優先度を下げる
  • C. プロセスがユーザー メモリ領域を割り当てる
  • D プロセスのタイムスライスサイズを増やす

プロセス IO 操作がブロックされています。セクションをバッファに読み取った後、オペレーティング システムは、ブロック状態から準備完了状態へのプロセスをスケジュールするように通知されます。

BCD は IO 操作とは何の関係もありません

最近長期間アクセスされていないページを除外対象として選択するアルゴリズムを () と呼びます。

  • オプション。
  • B LRU
  • C デッド
  • LFU

OPT (最適ページ置換アルゴリズム) は、どのページが最新に表示されるかを予測し、そのページを置換する
最適なページ置換アルゴリズムです。

LRU (Least Recent Used)
最も最近使用されていないページ置換アルゴリズム。つまり、最も長期間使用されていないページが最初に削除されます。
MFU (Most Frequently Used)
最も頻繁に使用されるアルゴリズム。最も頻繁に使用されるページを置き換えます。

LFU (Least Frequently Used) は、
使用頻度が最も低いページ置換アルゴリズムであり、一定期間内にアクセス頻度が最も低かったページを削除します。

同時プロセス間()。

  • お互いに何の関係もありません
  • B は同期する必要があります
  • C は相互に排他的でなければなりません
  • D は同期または相互排他を必要とする場合があります

相互排他:
異なるタスク間を移動する多数のプログラム フラグメントを指します。タスクがプログラム フラグメントの 1 つを実行すると、他のタスクはいずれも実行できなくなり、タスクがこのプログラム フラグメントの実行を終了するまで待機することしかできません。プログラム フラグメントは次のように指定できます。作成後にのみ実行します最も基本的なシナリオは、パブリック リソースは一度に 1 つのプロセスまたはスレッドによってのみ使用でき、複数のプロセスまたはスレッドがパブリック リソースを同時に使用することはできません。

同期:
異なるタスク間を移動する多数のプログラム フラグメントを指します。それらの操作は、特定の指定された順序に従って厳密に実行される必要があります。この順序は、完了する特定のタスクによって異なります最も基本的なシナリオは、2 つ以上のプロセスまたはスレッド プールが調整され、あらかじめ決められた順序で実行されるというものです。たとえば、タスク A の動作はタスク B によって生成されたデータに依存します。
明らかに、同期はより複雑な相互排他であり、相互排他は特殊な種類の同期です。

I/O 操作の終了は () になる場合があります。

  • A プロセスがスリープからレディに変わります
  • B いくつかのプロセスがスリープ状態から準備完了状態に変更されました
  • C プロセスがスリープ状態から実行状態に変化する
  • D いくつかのプロセスがスリープ状態から実行中に変更されました

ユーザープロセスが read システムコールを通じてディスクファイルからデータを読み取る場合、このプロセスに関する次の説明のうち正しいものはどれですか ( )。Ⅰ.ファイルのデータがメモリ上にない場合、プロセスはスリープ待機状態 II に移行します。読み取りシステム コールを要求すると、CPU はユーザー モードからカーネル モード III に切り替わります。read システムコールの引数にはファイル名を含める必要があります。

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

read は io 読み取り、1. ディスクがデータをメモリに読み取ります、2. CPU がメモリからデータを取得します (高速)、

Ⅰ. ファイルのデータがメモリにない場合、スリープ モードに入る目的は、メモリがファイルをディスクにマッピングするのを待つことであり、ディスクの読み取りが遅いため、スリープ モードに移行します。
Ⅱ. read はシステムコールなので、CPU はユーザーモードからコアモードに切り替わります。
Ⅲ. open システムコールにはファイル名が含まれ、読み取り専用には入力ストリームが含まれます。

Linux のファイル権限は 10 桁の長さで 4 つのセクションに分かれています。3 番目のセクションは何を表しますか ()?

  • ファイルの種類
  • B ファイル所有者の権限
  • C ファイルを所有するグループの権限
  • D 他のユーザーの権限

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

読み書きロックの記述については、以下が正しいです()

  • A ロック許可を取得できるスレッドは常に 1 つだけです。
  • B 読み取り/書き込みロックは、リーダーとライターに対して同時に存在することができます。
  • C 読み取り/書き込みロックが書き込みロック状態にある場合、書き込み操作を実行している他のスレッドはブロックされず、常にループして読み取り/書き込みロックが使用可能かどうかを確認します。
  • D 読み取り/書き込みロックは、読み取りロック状態での読み取り共有に使用できます。

書き込みロックがロックされると、他のスレッドは読み取り操作 (読み取りロックの適用) または書き込み操作 (書き込みロックの適用)、つまり書き込みと書き込みの相互排他、読み取りと書き込みの相互排他を実行できなくなります。

読み取りロックがロックされている場合、他のスレッドも読み取り操作、つまり読み取りと読み取りの同時実行を実行できます。

プロセスがブロックされる理由には ________ は含まれません。

  • タイムスライスの切り替え
  • B 等待I/O
  • Cプロセススリープ
  • D ロック解除待ち

分析: プロセスには、準備完了状態、実行状態、ブロック状態の 3 つの状態があります。3 つの状態間の遷移には、準備完了 -> 実行、実行 -> 準備完了、実行 -> ブロック中、ブロック中 -> 準備完了、I/O 待機、プロセス スリープ、ロック解除待機などがあり、その他の理由によりプロセスが一時停止します。「タイムスライスの切り替え」については、プロセスがCPU以外のリソースを全て獲得した場合は準備完了状態となり、タイムスライスが割り当てられると実行状態となり、タイムスライスが使い果たされると実行状態となります。はブロッキング状態にはならず、引き続き準備完了状態に入ります。したがって、プロセスの準備とブロックはまったく異なります。

ページフォールト処理中に、オペレーティングシステムによって実行される操作は () になる場合があります。Ⅰ.ページテーブル II を変更します。ディスク I/O Ⅲ.ページフレームを割り当てる

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

ページフォールト:
仮想メモリ導入後の概念です。オペレーティングシステムの起動後、仮想アドレステーブルがメモリ内に維持され、プロセスに必要な仮想アドレスが仮想アドレステーブルに記録されます。プログラムがロードされて実行されるとき、その一部だけがメモリにロードされ、残りの部分は必要に応じてディスクからロードされます。
メモリにロードされた部分は「常駐」としてマークされ、メモリにロードされなかった部分は「非常駐」としてマークされます。オペレーティング システムは、必要に応じて仮想アドレス テーブルを読み取ります。仮想アドレス テーブルに記録されたアドレスが「非常駐」としてマークされている場合、アドレスのこの部分に記録されているプログラム コードがメモリにロードされていないことを意味します。この状況は「ページの欠落」を意味します。

ページフレーム:
仮想メモリ(論理アドレス)のアドレスを物理メモリのアドレスに自動変換する回路をCPUに追加し、この回路を簡素化するためにRAMを4KBまたは8KBの長さのブロックに分割します。このブロックをページフレームと呼びます。
カーネルは物理メモリを管理するための基本単位としてページ フレームを使用します。ページング単位では、ページとはプロセスの仮想メモリに格納されるデータのグループを指し、このデータのグループを格納する物理メモリがページ フレームです。このデータ グループが解放されるとき、他のプロセスがこのメモリへのアクセスを要求すると、ページ フレーム内のページが変更されます。


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

年末賞——ダイナミック企画

シャオドンが働いている会社は年末ボーナスを発行する予定で、シャオドンはたまたま最高額の手当を受け取ることになり、会社の年次総会で抽選ゲームに参加することになりました。ゲームは 6*6 のチェス盤でプレイされます。 36 個のさまざまな値のピースがその上に置かれています。ギフト、それぞれの小さなチェス盤にギフトが置かれています。彼は左上隅からゲームを開始する必要があります。彼は一度に 1 ステップ下または右へしか移動できません。右下隅で停止します。途中でシャオドンはグリッド内のギフトを獲得できます。さあ、シャオドンが最高額のギフトを獲得できるようにアルゴリズムを設計してください。

6*6 マトリックスボードの場合、各要素は対応するグリッドのギフト値であり、左上隅は [0,0] です。各ギフトの値が大きくなるように、取得できる最大値を返してください。 100 未満、1000 未満。

import java.util.*;

public class Bonus {
    
    
    public int getMost(int[][] board) {
    
    
        // write code here
        for (int i = 0; i < board.length; i++) {
    
    
            for (int j = 0; j < board[0].length; j++) {
    
    
                if (i == 0 && j == 0) {
    
    
                    continue;
                } else if (i == 0) {
    
     // 上面没有 最大值就是 加上前一个
                    board[i][j] += board[i][j - 1];
                } else if (j == 0) {
    
     // 左边没有 最大值就是 加上上一个
                    board[i][j] += board[i - 1][j];
                } else {
    
     // 加左一个和上一个的最大值
                    board[i][j] += Math.max(board[i][j - 1], board[i - 1][j]);
                }
            }
        }
        // 返回最后一个
        return board[board.length - 1][board[0].length - 1];
    }
}

迷路問題 - 再帰

5 × 5 配列の場合は次のように、2 次元配列 N*M を定義します。
int maze[5][5] = { 0, 1, 0, 0, 0, 0 , 1, 1, 1, 0, 0 , 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, };これは迷路を表し、1 は壁を表し、0 は移動できるパスを表します。斜めではなく、横または垂直に歩くだけで、左上隅から右下隅までのルートを見つけるためのプログラミングが必要です。エントリ ポイントは [0,0]、つまり最初のグリッドが最適です。






データ範囲: 2≤n,m≤10、入力内容には 0≤val≤1 のみが含まれます

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

输入两个整数,分别表示二维数组的行数,列数。再输入相应的数组,其中的1表示墙壁,0表示可以走的路。数据保证有唯一解,不考虑有多解的情况,即迷宫只有一条通道。

出力の説明:

左上角到右下角的最短路径,格式如样例所示。

入力

5 5
0 1 0 0 0
0 1 1 1 0
0 0 0 0 0
0 1 1 1 0
0 0 0 1 0

出力

(0,0)
(1,0)
(2,0)
(2,1)
(2,2)
(2,3)
(2,4)
(3,4)
(4,4)

【問題解決のアイデア】

それぞれの場所には 4 つの方向があります:
進むことができる方向: 境界線を越えない、障害物がない、前を歩くことができない

検索:
現在位置 (x, y):
(x, y) が境界を越えたかどうか、(x, y) が以前に通過したかどうか、(x, y) に障害物があるかどうかを判断します
。障害物がない:

  1. 現在の場所をパスに保存
  2. (x, y) は右下隅、終了位置です: 新しいパスが生成されます。
    新しいパスがより短いパスであるかどうかを判断します。より短いパスである場合は、パスを更新します。
  3. (x,y) 4方向を探索し続ける
  4. パスから現在の場所を削除し、新しいパスを検索します
import java.util.*;

// 存放当前位置 (x, y)
class Node {
    
    
    int x;
    int y;

    public Node(int x, int y) {
    
    
        this.x = x;
        this.y = y;
    }
}

public class Main {
    
    
    public static void main(String[] args) {
    
    
        Scanner scanner = new Scanner(System.in);
        // 迷宫矩阵
        int row = scanner.nextInt();
        int col = scanner.nextInt();
        int[][] maze = new int[row][col];
        for (int i = 0; i < row; i++) {
    
    
            for (int j = 0; j < col; j++) {
    
    
                maze[i][j] = scanner.nextInt();
            }
        }
        // 搜索最短路径
        ArrayList<Node> path = new ArrayList<>();
        ArrayList<Node> minPath = new ArrayList<>();
        int[][] book = new int[row][col];
        getMinPath(maze, row, col ,0, 0, book, path, minPath);
        // 打印最短路径
        for (Node node : minPath) {
    
    
            System.out.println("(" + node.x + ","  + node.y + ")");
        }
    }

    /**
     * @param maze 迷宫矩阵
     * @param row col 行 列
     * @param x y 当前位置
     * @param book 标记当前矩阵,标记当前位置是否走过
     * @param path 保存当前路径的每一个位置
     * @param  minPath 记录最短路径
     */
    private static void getMinPath(int[][] maze, int row, int col, int x, int y, int[][] book, ArrayList<Node> path, ArrayList<Node> minPath) {
    
    
        // 1、判断 (x, y) 是否越界、走过、有障碍
        if (x < 0 || x >= row || y < 0 || y >= col
                || book[x][y] == 1 || maze[x][y] == 1) {
    
    
            return;
        }
        // 2、把当前位置 存入路径
        path.add(new Node(x, y));
        // 3、标记当前为位置
        book[x][y] = 1;
        // 4、判断当前位置是否为出口
        if (x == row - 1 && y == col - 1) {
    
    
            // 到出口,一条新的路径产生,判断是否要更新最短路径
            if (minPath.isEmpty() || path.size() < minPath.size()) {
    
    
                minPath.clear();
                for (Node node : path) {
    
    
                    minPath.add(node);
                }
            }
        }
        // 5、继续搜索以 (x, y) 的上下左右四个方向
        getMinPath(maze, row, col, x - 1, y, book, path, minPath);
        getMinPath(maze, row, col, x + 1, y, book, path, minPath);
        getMinPath(maze, row, col, x, y - 1, book, path, minPath);
        getMinPath(maze, row, col, x, y + 1, book, path, minPath);
        // 6、回退到当前位置,把当前位置,从路径中删除,寻找新的路径
        path.remove(path.size() - 1);
        book[x][y] = 0;
    }
}

いくつかの根

数値の根は、数値の桁を加算することで求めることができます。結果が 1 桁の数値の場合はその数値がルートとなり、結果が 2 桁の数値またはそれ以上の桁の数値の場合は数値を加算します。1桁になるまでこの方法を続けます。
たとえば、24 の場合、2 と 4 を足すと 6 になります。6 は 1 桁なので、6 は 24 の根です。
別の例は 39 です。3 と 9 を加算すると 12 が得られます。12 は 1 桁ではないため、1 と 2 を加算し、最終的に 3 が得られます。これは 1 桁なので、3 は 39 の根です。
ここで、正の整数が与えられ、そのルートが出力されます。
説明を入力してください:

输入包含多组数据。

每组数据数据包含一个正整数n(1≤n≤10E1000)。

出力の説明:

对应每一组数据,输出该正整数的数根。

入力

24
39

出力

6
3

【問題解決のアイデア】

正の整数 n のツリー ルートを見つけます。n の範囲は [1,10^1000] です。int
と long はどちらも値の範囲内にありません。現時点で入力データを受け取るには、次の型のみが考慮されます。

(1) BigDecimal
(2) 文字列

各桁の足し算が求められる問題ですが、比較的、String を使って 0 からたどって加算する方が簡単です
注意点:
(1) 足し算後の結果が 1 桁にならない、つまり条件を満たさない場合があります。ツリー。ルート要件を再度追加する必要があります。
たとえば、759 の場合、7+5+9=21 となり、これは 1 桁ではありません。再計算する必要があります: 2+1=3、ルート(2)文字列には
charAt が使用できます (int Index) メソッドで文字を取得します 文字を直接 int 特殊文字に変換できます
文字が 0 ~ 9 の数字の場合、文字と文字を使用できます'9' ~ '6 などの数値の差を取得する文字減算演算。
戻り値は 9-6 の結果 3 です。
したがって、文字 '0" ~ '9 の場合、int 値を取得するには、次を使用します。文字 -「0」 (文字「5」など)
。数値 5 を取得するには、「5-0」を使用します。

// write your code here
import java.util.*;

public class Main {
    
    
    public static void main(String[] args) {
    
    
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNext()) {
    
    
            String n = scanner.nextLine(); // next
            while (n.length() > 1) {
    
     // 字符串 "10" --> len > 1 而不是 10
                int sum = 0;
                for (int i = 0; i < n.length(); i++) {
    
    
                    sum += n.charAt(i) - '0'; // 各位相加
                }
                n = String.valueOf(sum);
            }
            System.out.println(n);
        }
    }
}

星間コード

100 年にわたる星間戦争の後、NowCoder はついにエイリアンのコードを解読しました。彼らのパスワードは整数の文字列であり、テーブル内の情報を通じて最後の 4 桁のパスワードにマッピングされます。表の規則は次のとおりです。n に対応する値は行列の n 乗の左上隅です。
|1 1|^n => |Xn …|
|1 0| |… …|
たとえば、n=2 の場合、
|1 1|^2 => |1 1| * |1 1| => |2 1 |
| 1 0| |1 0| |1 0| |1 1|
つまり、2に対応する数字は「0002」です。

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

输入有多组数据。
每组数据两行:第一行包含一个整数n (1≤n≤100);第二行包含n个正整数Xi (1≤Xi≤10000)

出力の説明:

对应每一组输入,输出一行相应的密码。

入力

6
18 15 21 13 25 27
5
1 10 100 1000 10000

出力

418109877711037713937811
00010089410135017501

【問題解決のアイデア】

f(xi)のフィボナッチデータを事前に用意
テストケースのグループを複数受け取る テスト
ケースの各グループ:
1行目:整数nを入力
2行目:n個の数値xiを
入力 出力:各xiを計算、 f(xi), all 結果は文字列に連結されます

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

import java.util.*;

public class Main {
    
    
    public static void main(String[] args) {
    
    
        // 准备斐波那契数列
        int[] nums = new int[10001];
        nums[1] = 1; // 从 1 开始,对应
        nums[2] = 2;
        for (int i = 3; i < 10001; i++) {
    
    
            nums[i] = nums[i - 1] + nums[i - 2];
            nums[i] = nums[i] % 10000; // 如果大于4位的则只输出最后4位
        }
        // 多组测试用例
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNextInt()) {
    
    
            StringBuilder stringBuilder = new StringBuilder();
            int n = scanner.nextInt();
            for (int i = 0; i < n; i++) {
    
    
                int xi = scanner.nextInt();
                // 拼接每个 xi 的密码   格式化输出 如果这个数不足4位则用0填充
                stringBuilder.append(String.format("%04d", nums[xi]));
            }
            // 输出 n 个拼接的密码串
           System.out.println(stringBuilder.toString());
       }
    }
}

ボウルに入ってくる

猫は容器(ボウルなど)に体を入れるのが好きですが、ボウルの周囲が猫の体長より短い場合は中に入ることができません。

次に、ボウルの長さと半径を教えて、ボウルに入るかどうかを判断してください。

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

输入有多组数据。

每组数据包含两个整数n (1≤n≤2^128) 和r (1≤r≤2^128),分别代表喵的身长和碗的半径。

圆周率使用3.14。

出力の説明:

对应每一组数据,如果喵能装进碗里就输出“Yes”;否则输出“No”。

入力

6 1
7 1
9876543210 1234567890

出力

Yes
No
No

1、ダブル

import java.util.*;

public class Main {
    
    
    public static void main(String[] args) {
    
    
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNext()) {
    
    
            double height = scanner.nextDouble();
            double r = scanner.nextDouble();
            if (2 * 3.14 * r < height) {
    
    
                System.out.println("No");
            } else {
    
    
                System.out.println("Yes");
            }
        }
    }
}

2、BigDecimal

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

注: import java.math.BigDecimal;

import java.util.*;
import java.math.BigDecimal;

public class Main {
    
    
    public static void main(String[] args) {
    
    
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNext()) {
    
    
            BigDecimal n = scanner.nextBigDecimal();
            BigDecimal r = scanner.nextBigDecimal();
            BigDecimal len = new BigDecimal("6.28").multiply(r);
            // 身长 比 周长 长,进不去
            System.out.println(n.compareTo(len) == 1 ? "No" : "Yes");
        }
    }
}

ジャンプステップ展開問題

カエルは一度に 1 段ずつジャンプすることも、2 段ずつジャンプすることもできます。また、n 段ジャンプすることもできます。カエルが n レベルのステップ (n は正の整数) をジャンプできる方法が何通りあるかを調べてください。

データ範囲: 1≤n≤20
上級: 空間計算量 O(1)、時間計算量 O(1)

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

本题输入仅一行,即一个整数 n 

出力の説明:

输出跳上 n 级台阶的跳法

入力

3

出力

4

【問題解決のアイデア】

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

public class Solution {
    
    
    public int jumpFloorII(int target) {
    
    
        return 1 << --target;
    }
}

公式の再帰問題の解決策:

この質問に関しては、n 段階の n 段階のジャンプがあることが前提となります。以下のように分析します。

f(1) = 1

f(2) = f(2-1) + f(2-2) //f(2-2) は、第 2 レベルが一度に第 2 レベルにジャンプする回数を表します。

f(3) = f(3-1) + f(3-2) + f(3-3)

f(n) = f(n-1) + f(n-2) + f(n-3) + … + f(n-(n-1)) + f(nn)

例証します:

1) ここでの f(n) は、ステップ 1、2、...n の 1 つのジャンプ方法による n ステップの数を表します。

2) n = 1 の場合、ジャンプ方法は 1 つだけあり、f(1) = 1

3) n = 2 の場合、一度に 1 次または 2 次の 2 つのジャンプ方法があり、問題 (1) に戻ります。 f(2) = f(2-1) + f(2-2)

4) n = 3 の場合、レベル 1、レベル 2、レベル 3 の 3 つのジャンプ方法があります。

初めてレベル 1 から飛び出すと、残るのは f(3-1); 初めてレベル 2 から飛び出すと、f(3-2) が残ります。レベル 3 を終了すると、 f(3-3) が残ります)

したがって、結論は f(3) = f(3-1)+f(3-2)+f(3-3) となります。

5) n = n时,会有n中跳的方式,  1阶、2阶...n阶,得出结论: 

f(n) = f(n-1)+f(n-2)+…+f(n-(n-1)) + f(nn) => f(0) + f(1) + f (2) + f(3) + … + f(n-1)

6) 上記はすでに結論ですが、簡単にするために、さらに単純化することができます。

f(n-1) = f(0) + f(1)+f(2)+f(3) + … + f((n-1)-1) = f(0) + f(1) + f(2) + f(3) + … + f(n-2)

f(n) = f(0) + f(1) + f(2) + f(3) + … + f(n-2) + f(n-1) = f(n-1) + f (n-1)

次のように結論付けることができます。

f(n) = 2*f(n-1)

7) 最終的な結論として、n 個のステップで一度にステップ 1、2、...n がある場合、合計のジャンプ方法は次のようになります。

| 1 ,(n=0)

f(n) = | 1 ,(n=1)

| 2*f(n-1),(n>=2)

public class Solution {
    
    
    public int jumpFloorII(int target) {
    
    
        if (target <= 0) {
    
    
            return -1;
        } else if (target == 1) {
    
    
            return 1;
        } else {
    
    
            return 2 * jumpFloorII(target - 1);
        }
    }
}

三角形

3 つの辺が与えられ、三角形を形成できるかどうかを判断してください。

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

输入包含多组数据,每组数据包含三个正整数a、b、c(1≤a, b, c≤10^100)。

出力の説明:

对应每一组数据,如果它们能组成一个三角形,则输出“Yes”;否则,输出“No”。

入力

1 2 3
2 2 2

出力

No
Yes

1、ダブル

import java.util.*;

public class Main {
    
    
    public static void main(String[] args) {
    
    
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNextDouble()) {
    
    
            double a = scanner.nextDouble();
            double b = scanner.nextDouble();
            double c = scanner.nextDouble();
            if ((a > (c - b)) && (a > (b - c)) && (b > (a - c))) {
    
    
                System.out.println("Yes");
            } else {
    
    
                System.out.println("No");
            }
        }
    }
}

2、BigDecimal

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

import java.util.*;
import java.math.*;

public class Main {
    
    
    public static void main(String[] args) {
    
    
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNext()) {
    
    
            BigDecimal a = scanner.nextBigDecimal();
            BigDecimal b = scanner.nextBigDecimal();
            BigDecimal c = scanner.nextBigDecimal();
            if (a.add(b).compareTo(c) > 0
               && a.add(c).compareTo(b) > 0
               && b.add(c).compareTo(a) > 0) {
    
    
                System.out.println("Yes");
            } else {
    
    
                System.out.println("No");
            }
        }
    }
}

奇数桁はすべて奇数、または偶数桁はすべて偶数

import java.util.*;

public class Solution {
    
    
    public void oddInOddEvenInEven(int[] array) {
    
    
        int m = 0; // 偶数位
        int n = 1; // 奇数位
        while (m < array.length && n < array.length) {
    
    
            if (array[m] % 2 == 0) {
    
    
                m += 2;
                continue;
            }
            if (array[n] % 2 != 0) {
    
    
                n += 2;
                continue;
            }
            // 偶数位是奇数 奇数位是偶数 交换
            int tmp = array[m];
            array[m] = array[n];
            array[n] = tmp;
        }
    }
}

桃を分ける猿

老猿は生涯一生懸命働き、子猿の群れに莫大な財産、つまりたくさんの桃を残しました。老猿はこれらの桃を小猿にあげることにしました。
最初の猿がやって来て、桃を5つの山に分けましたが、その5つの山の数は同じで、もう1つありました。残りの1匹は老猿に任せて、自分でたくさん食べました。
2番目の猿が来て、桃を5つの山に分けましたが、その5つの山の数は同じで、もう1つありました。余分な一匹は老猿に任せて、自分でたくさん食べました。
その後、子猿もそれに続きました。結局、残った桃はすべて老猿に預けられました。
ここには n 匹の小猿がいます。最初に少なくとも何個の桃があり、少なくとも最後に老猿が何個の桃を手に入れることができるかを計算するプログラムを書いてください。
説明を入力してください:

输入包括多组测试数据。
每组测试数据包括一个整数n(1≤n≤20)。
输入以0结束,该行不做处理。

出力の説明:

每组测试数据对应一行输出。
包括两个整数a,b。
分别代表开始时最小需要的桃子数,和结束后老猴子最少能得到的桃子数。

入力

5
1
0

出力

3121 1025
1 1

【問題解決のアイデア】

// write your code here
import java.util.*;

public class Main {
    
    
    public static void main(String[] args) {
    
    
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNext()) {
    
    
            int n = scanner.nextInt();
            if (n == 0) break;
            long a = (long) (Math.pow(5, n) - 4);
            long b = (long) (Math.pow(4, n) + n - 4);
            System.out.println(a + " " + b);
        }
    }
}

偽造コインもある

実は偽造コインもあるんです!今、豚肉の価格は上がっていますが、農家の賃金は上がっていません。お金がないのにどうやって豚肉を買えばいいのでしょうか? nowcoder さんは豚肉を買いに行きましたが、手に入れたお釣りには偽のコインが入っていました。Nowcoder が誤って本物のコインの山にそれを混ぜてしまったのは残念です。あなたが知っているのは、偽造通貨の重量が本物の通貨の質量よりも軽いということだけです。秤(秤の両端には無限の硬貨を入れることができます)を与えて、忌まわしい偽造通貨を最速で見つけてください。

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

1≤n≤2^30,输入0结束程序。

出力の説明:

最多要称几次一定能把那个假币找出来?

入力

3
12
0

出力

1
3

【問題解決のアイデア】

紙幣の山の中から偽造紙幣を見つける最も早い方法は、紙幣を 3 つの山に分割し、そのうちの 2 つの山を使って重さを量ることです。

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

偽造コインは本物のコインより軽いため、
(1) A<B の場合、偽造コインは A にあります。
(2) A>B の場合、偽造コインは B にあります。
(3) A=B の場合、偽造コインは B にあります。偽造コインはCにあります

通貨の山を 3 つの部分に分割することは、偽造通貨を見つける最も早い方法です。
問題は、何回重さを量る必要があるかを尋ねるので、最悪のシナリオは偽造通貨が常に最も多い 3 つの部分にあるということです。
n 通貨、n 範囲は [1, 2^30] で、毎回 3 つの部分に分割され、最大部分である n/3 を見つけて切り上げます。
n=4 の場合、1、1、2 に分割され、最大数は 2 になります。
n=5 の場合、2、2、1 に分割され、最大数は 2 になります。

問題解決のアイデア:
n 個の通貨を継続的に循環し、毎回それらを 3 つの部分に分割し、n=1 または n=2 になるまで最大部分 (n/3 は切り上げ) を取得します。

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

Math.ceil()メソッドを使用できます

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

n/3 は int / int であり、戻り値も int であり、小数点が失われていることに注意してください。
(double)n/3 を使用して浮動小数点数を返し、それを a として渡す必要があります。 Math.ceil()) メソッドのパラメータ、
つまり Math.ceil((double)n/3)

import java.util.Scanner;

public class Main {
    
    
    public static void main(String[] args) {
    
    
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNextInt()) {
    
    
            int n = scanner.nextInt();
            if (n == 0) {
    
    
                break;
            }
            int count = 0;
            while (n >= 2) {
    
    
                n = (int) Math.ceil((double)n / 3);
                count++;
            }
            System.out.println(count);
        }
    }
}

正の数の配列の形成不可能な最小和を見つける - 動的計画法

すべて正の数である配列 arr を指定して、arr の形成不可能な最小合計の概念を定義します。 1. arr の空でないすべてのサブセットの中で、各サブセット内のすべての要素を合計すると、多くの値が得られます。その中で最も小さい値は次のとおりです。レコードは min であり、最大のものは max として記録されます; 2. 区間 [min, max] 内に、arr の特定のサブセットを加算しても取得できない正の数値がある場合、これらの正の数値のうちの最小の数値が記録されます。数値は arr の最小値です 合計は形成できません; 3. 区間 [min, max] で、すべての数値を arr の特定のサブセットで加算できる場合、max+1 は arr の形成不可能な最小合計です; 例: arr = {3 ,2,5} arr の最小値は 2 で、最大値は 10 です。区間 [2,10] では、4 はサブセットを追加しても取得できない最小値であるため、4 は形成不可能な最小値です。 arr の合計 ; arr = {3,2,4} arr の最小値は 2 で、最大値は 9 です。区間 [2,9] では、8 はサブセットを追加しても取得できない最小値であるため、 8 は arr の最小構成不可能合計 arr の最小構成不可能合計; arr の最小構成不可能合計を返す関数を作成してください。

【問題解決のアイデア】

arr = {3,2,5} サブセットとサブセットの合計は次のようになります。

  • {3}=3

  • {2}=2

  • {5}=5

  • {3.2}=5

  • {3,5}=8

  • {2,5}=7

  • {3.2.5}=10

サブセットの最小合計は 2、サブセットの最大合計は
[2,10] の範囲で 10、サブセットの不可能な最小合計は 4 です。

j が arr の可能なサブセットの合計 ([2,10] の範囲内の任意の値) を表し、f() がそれが可能かどうかを表すものとします。次に
例を示します。

  • f(2) = 真
  • f(3) = 真
  • f(4) = false

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

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

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

public class Solution {
    
    
	/**
	 *	正数数组中的最小不可组成和
	 *	输入:正数数组arr
	 *	返回:正数数组中的最小不可组成和
	 */
	public int getFirstUnFormedNum(int[] arr) {
    
    
        int min = Integer.MAX_VALUE;
        int max = 0;
        for (int i : arr) {
    
    
            min = Math.min(min, i);
            max += i;
        }
        boolean[] result = new boolean[max + 1];
        result[0] = true;
        for (int o : arr) {
    
     // 遍历数组元素
            for (int j = max; j >= o; j--) {
    
     // 遍历 max-min 向后往前到 o
                result[j] = result[j - o] || result[j]; // 本身就是
            }
        }
        for (int j = min; j < result.length; j++) {
    
     // result 中为 false 的就是不可组成
            if (!result[j]) {
    
    
                return j;
            }
        }
        return max + 1;
	}
}

最も難しい質問

NowCoder は危険と陰謀に満ちた時代に生きています。生き残るために、彼は軍事メッセージに使用される最初の暗号を発明しました。あなたが陸軍の将校で、送信されたメッセージを解読して
将軍に提供する必要があるとします。
メッセージ暗号化の方法は、元のメッセージの各文字をその文字の後の 5 番目の文字に置き換えることであり (例: 元のメッセージの各文字 A は文字 F に置き換えられます)、他の文字は変更されません。元のメッセージは大文字です。パスワードの文字と原文の文字の対応は以下のとおりです。
パスワード文字: ABCDEFGHIJKLMNOPQRSTU VWXYZ
元の文字: VWXYZABCDEFGHIJKLMNOP QRSTU
入力説明:

输入包括多组数据,每组数据一行,为收到的密文。
密文仅有空格和大写字母组成。

出力の説明:

对应每一组数据,输出解密后的明文。

入力

HELLO WORLD<br/>SNHJ

出力

CZGGJ RJMGY<br/>NICE
import java.util.*;

public class Main {
    
    
    public static void main(String[] args) {
    
    
        Scanner scanner = new Scanner(System.in);
        String letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        while (scanner.hasNextLine()) {
    
    
            String s = scanner.nextLine();
            StringBuilder stringBuilder = new StringBuilder();
            for (int i = 0; i < s.length(); i++) {
    
    
                if (Character.isLetter(s.charAt(i))) {
    
    
                    int index = letters.indexOf(s.charAt(i)); // 在字母串中的位置
                    index = (index - 5 + 26) % 26; // 前 5 个 字母 ABCDE 对应后面 TUVWX
                    stringBuilder.append(letters.charAt(index));
                } else {
    
     // 非字母 不需要转
                    stringBuilder.append(s.charAt(i));
                }
            }
            System.out.println(stringBuilder.toString());
        }
    }
}

文字変換操作:
(1) 次のように、int と char は相互に変換できます:
System.out.println((int)'A'); // 65
System.out.println((char)68); / / D
(2 ) 2 つの大文字の減算は、int への変換後の減算と等しくなければなりません。この場合、次の結論が得られます: System.out.println
((char) ('A' + 2)) ; // C
System.out .println((char)('D' + 3)); // G
(3) 加算した値が 'Z' の値を超えられない場合は、それ以外の文字になります

スペースでない場合は大文字です。「E」以降の場合は、現在の文字-5に結合されます。「
A」-「E」の場合は、結合されます。現在のキャラクターに +21 を加えます。

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

import java.util.*;

public class Main {
    
    
    public static void main(String[] args) {
    
    
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNextLine()) {
    
    
            String s = scanner.nextLine();
            StringBuilder stringBuilder = new StringBuilder();
            for (int i = 0; i < s.length(); i++) {
    
    
                char c = s.charAt(i);
                if (c == ' ') {
    
    
                    stringBuilder.append(" ");
                } else {
    
    
                    stringBuilder.append((char) (c > 'E' ? c - 5 : c + 21));
                }
            }
            System.out.println(stringBuilder.toString());
        }
    }
}

因子の数

正の整数は、1 つ以上の配列の積に分解できます。たとえば、36=2 2 3*3 には、2 と 3 の 2 つの因数が含まれます。NowCoder は最近、因数の数の分布パターンを研究しており、一連の正の整数が与えられたとして、各正の整数の因数の数を出力するプログラムを開発してもらいたいと考えています。

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

输入包括多组数据。
每组数据仅有一个整数n (2≤n≤100000)。

出力の説明:

对应每个整数,输出其因子个数,每个结果占一行。

入力

30<br/>26<br/>20

出力

3<br/>2<br/>2

n の最速の因数を見つける方法は次のとおりです:
n = x * y
x<=y の場合、x は [2, root n] の範囲内にある必要があります
。つまり、[2] です。 、ルート n] No. n]、n の因数を見つける必要があります

import java.util.*;

public class Main {
    
    
    public static void main(String[] args) {
    
    
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNextInt()) {
    
    
            int n = scanner.nextInt();
            int count = 0;
            for (int i = 2; i <= Math.sqrt(n); i++) {
    
    
                if (n % i == 0) {
    
    
                    while (n % i == 0) {
    
    
                        n /= i;
                    }
                    count++; // 因子的个数
                }
            }
            if (n != 1) {
    
     // 素数 再加一
                count++;
            }
            System.out.println(count);
        }
    }
}

分解係数

いわゆる因数分解は、与えられた正の整数 a をいくつかの素数の積、つまり a = a1 × a2 × a3 × … × an、および 1 < a1 ≤ a2 ≤ a3 ≤ … ≤ an に分解することです。このうち、a1、a2、...、anはすべて素数です。まず整数aを与えて、分解した係数を出力してください。

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

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

出力の説明:

对应每组数据,以“a = a1 * a2 * a3...”的形式输出因式分解后的结果。

入力

10<br/>18

出力

10 = 2 * 5<br/>18 = 2 * 3 * 3
import java.util.*;

public class Main {
    
    
    private static void AllFactors(int n, List<Integer> factors) {
    
    
        // 注意等于 10-> 2 * 5 变成5时 如果是小于 退出循环 只有 2
        for (int i = 2; i <= n; i++) {
    
    
            if (n == 0) {
    
    
                return;
            }
            while (n != 0 && n % i == 0) {
    
    
                factors.add(i);
                n /= i;
            }
        }
    }
    
    public static void main(String[] args) {
    
    
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNextInt()) {
    
    
            int n = scanner.nextInt();
            List<Integer> factors = new ArrayList<>();
            AllFactors(n, factors);
            System.out.print(n + " = ");
            for (int i = 0; i < factors.size() - 1; i++) {
    
    
                System.out.print(factors.get(i) + " * ");
            }
            System.out.println(factors.get(factors.size() - 1));
        }
    }
}
import java.util.*;

public class Main {
    
    
    private static List<String> factorization(int a) {
    
    
        List<String> ans = new ArrayList<>();
        for (int i = 2; a > 1 && i * i <= a; i++) {
    
    
            while (a % i == 0) {
    
    
                ans.add(String.valueOf(i));
                a /= i;
            }
        }
        if (a > 1) {
    
    
            ans.add(String.valueOf(a));
        }
        return ans;
    }
    
    public static void main(String[] args) {
    
    
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNextInt()) {
    
    
            int a = scanner.nextInt();
            List<String> factors = factorization(a);
            System.out.printf("%d = %s\n", a, String.join(" * ", factors));
        }
    }
}

アメリカの休日

中国の祝日とは異なり、アメリカの祝日は通常、特定の月の曜日に基づいているため、祝日の日付は毎年異なります。具体的なルールは以下の通りです。
* 1月1日:元旦
* 1月の第3月曜日:マーティン・ルーサー・キング・ジュニアの日
* 2月の第3月曜日:大統領の日
* 5月の最終月曜日:戦没将兵追悼記念日
* 7月4日:第4回7 月の: 労働者の日
* 9 月の第 1 月曜日: 労働者の日
* 11 月の第 4 木曜日: 感謝祭
* 12 月 25 日: クリスマス
さて、1 年が与えられましたので、その年の祭りの日付を生成するのに協力してください。
説明を入力してください:

输入包含多组数据,每组数据包含一个正整数year(2000≤year≤9999)。

出力の説明:

对应每一组数据,以“YYYY-MM-DD”格式输出当年所有的节日日期,每个日期占一行。

每组数据之后输出一个空行作为分隔。

入力

2014
2013

出力

2014-01-01
2014-01-20
2014-02-17
2014-05-26
2014-07-04
2014-09-01
2014-11-27
2014-12-25

2013-01-01
2013-01-21
2013-02-18
2013-05-27
2013-07-04
2013-09-02
2013-11-28
2013-12-25

【分析】

質問 1: ymd が与えられた場合、その日が何曜日であるかを知るにはどうすればよいですか?

紀元前 1 年 12 月 31 日を基準値とすると、この日は日曜日 7 になります。

週の週(ymd):
間隔日 % 7 に基本週を加えたもので、第 7 週になる可能性があるため、%7、

間隔の日数:
(ymd) - (0000-12-31) = 年間の合計日数 + 昨年の日数
                                   ~~~~~~~~~~~~~~~~ ~~~~~~ ~~~~~~~~~~~~                                  = (y - 1)* 365+途中で経過した閏年数* 1+昨年の日数

[1,y) すべての年で、4 で割り切れる数: 切り捨て ((y - 1)/4) および (y - 1)/4 は切り捨てられて 100 で割り切れます: ( y -1)/
100は 400 で割り切れます: (y - 1) / 400
(y - 1) / 4 - (y - 1) / 100 + (y - 1) / 400 = 経験した閏年の合計数

                                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~                                    = 365* (y - 1) + (y- 1) / 4 - (y- 1) / 100 + (y - 1) / 400 + 昨年の日数

簡略化: 365 = 364 +1、364 = 52*7、つまり 365 を削除できます。

昨年の日数: 経過した丸月 + 日 + 閏年? 1 : 0

質問 2: m 月 1 日は平日であることがわかっていますが、それは何日ですか?

  • 曜日が 1 月 1 日である場合、1 月の第 3 月曜日を求めます。

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

  • 2月第3月曜日:同上
  • 曜日が 9 月 1 日である場合、9 月の最初の月曜日を見つけます。

9 月 1 日の月曜日であると仮定します。答えは 1 で、1 + 0 * 7 + (7 - w + 1) % 7 と書くことができます。

上の式を比較すると、月は1月から始まるのでn - 1です。第3月曜日を求めると、3-1=2となり、1 + (n - 1) * 7 + (7 - w +) 1) % 7 は1 + (1 - 1) * 7 + (7 - w + 1) % 7

  • 11月の第4木曜日:

1 + (n - 1) * 7 + (7 - w + 4) % 7 は、 1 + (4 - 1) * 7 + (7 - w + 4) % 7 の 4に置き換えることができます。

  • 公式:

f(w, n, e) = 1 + (n - 1) * 7 + (7 - w + e) % 7 w
: 今月 1 日の曜日、n : の数を求める今月、e: 曜日を調べます。

  • 5月の最後の月曜日:

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

コード:

import java.util.*;

public class Main {
    
    
    private static boolean isLeapYeat(int y) {
    
    
        return (y % 400 == 0) || (y % 4 == 0 && y % 100 != 0);
    }

    private static final int[] DAYS = {
    
    31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

    // 给定 y,m,d, 返回间隔天数
    private static int nDays(int y, int m, int d) {
    
    
        int n = d;
        for (int i = 0; i < m - 1; i++) {
    
    
            n += DAYS[i];
        }
        if (m > 2 && isLeapYeat(y)) {
    
    
            n++;
        }
        return n;
    }

    // 传入 y,m,d, 找到从公元前1年 12月31日开始过了多久。求它 MOD 7 的同余数
    private static int diff(int y, int m, int d) {
    
    
        return (y - 1) + (y - 1) / 4 - (y - 1) / 100 + (y - 1) / 400 + nDays(y, m, d);
    }

    // 根据 y,m,d, 求出星期几
    private static int week(int y, int m, int d) {
    
    
        int w = diff(y, m, d) % 7;
        if (w == 0) {
    
    
            w = 7;
        }
        return w;
    }

    // 根据 1 日的星期 w, 求第 n 个星期 e 是几号
    private static int m1(int w, int n, int e) {
    
    
        return 1 + (n - 1) * 7 + (7 - w + e) % 7;
    }

    // 根据 6月1日星期 w, 求 5月最后一个星期一
    private static int m2(int w) {
    
    
        int d = (w == 1 ? 7 : w - 1);
        return 32 - d;
    }

    public static void main(String[] args) {
    
    
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNextInt()) {
    
    
            int y = scanner.nextInt();

            System.out.printf("%d-01-01\n", y);

            int w = week(y, 1, 1);
            System.out.printf("%d-01-%02d\n", y, m1(w, 3, 1));

            w = week(y, 2, 1);
            System.out.printf("%d-02-%02d\n", y, m1(w, 3, 1));

            w = week(y, 6, 1);
            System.out.printf("%d-05-%02d\n", y, m2(w));

            System.out.printf("%d-07-04\n", y);

            w = week(y, 9, 1);
            System.out.printf("%d-09-%02d\n", y, m1(w, 1, 1));

            w = week(y, 11, 1);
            System.out.printf("%d-11-%02d\n", y,  m1(y, 4, 4));

            System.out.printf("%d-12-25\n", y);

            System.out.println();
        }
    }
}

タオバオストア

NowCoder はタオバオにオンライン ストアをオープンしました。彼は、月が素数の場合、その月は 1 日あたり 1 元を稼ぐことができ、それ以外の場合は 1 日あたり 2 元を稼ぐことができることを発見しました。
今度は一定期間を与えて、彼が総収入を計算するのを手伝ってください。

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

输入包含多组数据。

每组数据包含两个日期from和to (2000-01-01 ≤ from ≤ to ≤ 2999-12-31)。

日期用三个正整数表示,用空格隔开:year month day。

出力の説明:

对应每一组数据,输出在给定的日期范围(包含开始和结束日期)内能赚多少钱。

入力

2000 1 1 2000 1 31
2000 2 1 2000 2 29

出力

62
29
import java.util.Scanner;

public class Main {
    
    
    private static boolean isPrimeNum(int n) {
    
    
        if (n == 1) {
    
     // 有 1 单独返回
            return false;
        }
        for (int i = 2; i < n; i++) {
    
    
            if (n % i == 0) {
    
    
                return false;
            }
        }
        return true;
    }

    private static boolean isLeap(int y) {
    
    
        if (y % 4 == 0 && y % 100 != 0 || y % 400 == 0) {
    
    
            return true;
        }
        return false;
    }

    private static int income(int fromYear, int fromMonth, int fromDay, int toYear, int toMonth, int toDay) {
    
    
        int income = 0;
        int[] monthDays = {
    
    31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

        if (isLeap(fromYear)) {
    
     // 起始年 是闰年
            monthDays[1] = 29;
        }
        // 1、同一年 单独计算
        if (fromYear == toYear) {
    
    
            // fromMonth - toMonth-1
            for (int i = fromMonth; i < toMonth; i++) {
    
    
                if (isPrimeNum(i)) {
    
    
                    income += monthDays[i - 1];
                } else {
    
    
                    income += monthDays[i - 1] * 2;
                }
            }
            // 只有一个月 fromDay - toDay
            income += isPrimeNum(fromMonth) ? toDay - fromDay + 1: (toDay - fromDay + 1) * 2;
            return income;
        }

        // 计算起始年 fromMont - 12 的收益
        if (isPrimeNum(fromMonth)) {
    
     // fromMonth 可能不是从第一天开始
            income += monthDays[fromMonth - 1] - fromDay + 1;
        } else {
    
    
            income += (monthDays[fromMonth - 1] - fromDay + 1) * 2;
        }
        for (int i = fromMonth + 1; i <= 12; i++) {
    
     // fromMonth - 12
            if (isPrimeNum(i)) {
    
    
                income += monthDays[i - 1];
            } else {
    
    
                income += monthDays[i - 1] * 2;
            }
        }
        // 结束年不是闰年 改回 28
        if (!isLeap(toYear)) {
    
    
            monthDays[1] = 28;
        }
        // 计算结束年 1 - toMonth-1 的收益
        for (int i = 1; i < toMonth; i++) {
    
     // 结束年 月
            if (isPrimeNum(i)) {
    
    
                income += monthDays[i - 1];
            } else {
    
    
                income += monthDays[i - 1] * 2;
            }
        }
        // toMonth 的 toDay 收益
        income += isPrimeNum(toMonth) ? toDay : toDay * 2; // 结束年 日
        // 2、相隔一年 返回
        if (fromYear + 1 == toYear) {
    
    
            return income;
        }

        // 3、相隔多年 加中间年
        monthDays[1] = 28; // 改回 28
        // 2000 - 2002    ---> 2001-2001 需要取等于
        for (int i = fromYear + 1; i <= toYear - 1; i++) {
    
    
            if (isLeap(i)) {
    
    
                monthDays[1] = 29;
            } else {
    
    
                monthDays[1] = 28;
            }
            for (int j = 1; j <= 12; j++) {
    
    
                if (isPrimeNum(j)) {
    
    
                    income += monthDays[j - 1];
                } else {
    
    
                    income += monthDays[j - 1] * 2;
                }
            }
        }
        return income;
    }

    public static void main(String[] args) {
    
    
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNextInt()) {
    
    
            // 2000 1 1 2999 12 31    579243
            int fromYear = scanner.nextInt();
            int fromMonth = scanner.nextInt();
            int fromDay = scanner.nextInt();
            int toYear = scanner.nextInt();
            int toMonth = scanner.nextInt();
            int toDay = scanner.nextInt();
            int income = income(fromYear, fromMonth, fromDay, toYear, toMonth, toDay);
            System.out.println(income);
        }
    }
}
import java.util.Scanner;

public class Main {
    
    
    private static boolean isLeap(int y) {
    
    
        return (y % 4 == 0 && y % 100 != 0 || y % 400 == 0);
    }

    // 给定一年 整年的收益
    private static int annualIncome(int year) {
    
    
        return 2 * 31
                + 28
                + 31
                + 2 * 30
                + 31
                + 2 * 30
                + 31
                + 2 * 31
                + 2 * 30
                + 2 * 31
                + 30
                + 2 * 31
                + (isLeap(year) ? 1 : 0);
    }

    private static boolean isPrime(int month) {
    
    
        return month == 2 || month == 3 || month ==  5 || month == 7 || month == 11;
    }

    // 从一年1月1日 到这一年 m,d 的收益
    private static int profitThisYear(int year, int month, int day) {
    
    
        int profit = 0;
        if (!isPrime(month)) {
    
    
            profit = day * 2;
        } else {
    
    
            profit = day;
        }

        while (--month > 0) {
    
    
            switch(month) {
    
    
                case 1: case 8: case 10: case 12:
                    profit += 62;
                    break;
                case 3: case 5: case 7:
                    profit += 31;
                    break;
                case 4: case 6: case 9:
                    profit += 60;
                    break;
                case 11:
                    profit += 30;
                    break;
                default: // 2 月
                    profit += (28 + (isLeap(year) ? 1 : 0));
                    break;
            }
        }
        return profit;
    }

    public static void main(String[] args) {
    
    
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNextInt()) {
    
    
            int fromYear = scanner.nextInt();
            int fromMonth = scanner.nextInt();
            int fromDay = scanner.nextInt();
            int toYear = scanner.nextInt();
            int toMonth = scanner.nextInt();
            int toDay = scanner.nextInt();

            int profit = 0;
            // 起始年:整年 - 到fromDay之间 (注意减一)
            profit = annualIncome(fromYear) - profitThisYear(fromYear, fromMonth, fromDay - 1);
            // 同一年 2000 5 17 2000 7 1
            // —> 5.17到12.31的收益 - 全年
            // = 负的一月一号到5.16的收益 + 加后面结束年
            // = 负的一月一号到5.16的收益 + 一月一号到7.1
            // = 5.17 - 7.1 的收益
            if (fromYear == toYear) {
    
    
                profit -= annualIncome(fromYear);
            }
            // 结束年
            profit += profitThisYear(toYear, toMonth, toDay);
            // 中间年
            for (int i = fromYear + 1; i < toYear; i++) {
    
    
                profit += annualIncome(i);
            }
            System.out.println(profit);
        }
    }
}

フィボナッチフェニックステール

NowCoder は、1 から 100,000 までのすべてのフィボナッチ数を記憶したと主張しています。
彼をテストするために、私たちは彼にランダムに数字 n を与え、n 番目のフィボナッチ数を言うように頼みました。もちろん、フィボナッチ数は非常に大きくなります。したがって、n 番目のフィボナッチ数が 6 桁未満の場合はその数字を言い、それ以外の場合は最後の 6 桁だけを言います。

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

输入有多组数据。
每组数据一行,包含一个整数n (1≤n≤100000)。

出力の説明:

对应每一组输入,输出第n个斐波那契数的最后6位。

入力

1<br/>2<br/>3<br/>4<br/>100000

出力

1<br/>2<br/>3<br/>5<br/>537501
// write your code here
import java.util.*;

public class Main {
    
    
    public static void main(String[] args) {
    
    
        int border = -1;
        int[] array = new int[100000];
        array[0] = 1;
        array[1] = 2;
        for (int i = 2; i < 100000; i++) {
    
    
            array[i] = array[i - 1] + array[i - 2];
            if (border == -1 && array[i] >= 1000000) {
    
     // 超过6位数 记录
                border = i + 1;
            }
            array[i] %= 1000000; // 用 border,后取模
        }
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNextInt()) {
    
    
            int n = scanner.nextInt();
            if (n < border) {
    
    
            System.out.printf(array[n - 1]);
            } else {
    
    
                System.out.printf("%06d\n", array[n - 1]);
            }   
        }
    }
    
    public static void main1(String[] args) {
    
    
        // 提前计算
        int[] array = new int[100000];
        array[0] = 1;
        array[1] = 2;
        for (int i = 2; i < 100000; i++) {
    
    
            array[i] = (array[i - 1] + array[i - 2]) % 1000000;
        }
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNextInt()) {
    
    
            int n = scanner.nextInt();
            // 补 0
            System.out.printf(n < 25 ? "%d\n" : "%06d\n", array[n - 1]);
        }
    }
}

おすすめ

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