番号を報告してゲームを終了します

トピック情報

順番に並べられたn人のサークルがあります。最初の人から数え始めます(1から3まで)。3に報告する人は誰でもサークルから撤退し、最後に残っている元の番号は誰であるかを尋ねます。

回答

このトピックは比較的古典的で、ジョセフリング問題としても知られています。興味のある友達はジョセフリングを検索できます。

簡単な例を挙げて、10人で番号を報告してから、終了します。

10人と比較したアレイの位置が出口の問題を報告しました

上記の例から、次のことがわかります。

  1. 初期配列を定義します。配列位置の初期値は0です。
  2. カウンターは、値が0の数のみを報告します
  3. カウンターが3と報告したら、位置の値を1に変更すると、残りの人数が1人減ります。
  4. ループで番号をアナウンスし、残りの番号が1になったら終了します
  5. 配列が最後までループすると、配列の位置は0に設定されます
  6. ループ位置の値が0でない場合、1を加算した後に位置が移動します
  7. ループが終了したら、配列を出力して0の位置を出力します

コーディング

配列の実装

上記の問題の分析によると、アルゴリズムを実現するために配列を使用してください

	/**
	 * 报数退出
	 * @param m 总人数
	 * @param n 报到n时退出
	 */
	public static void reportNumber(int m, int n) {
		// 初始化数组长度为m,初始化报数器speaker为0
		int[] arr = new int[m];
		int speaker = 0;
		
		// 初始化剩余人数left为m,数组元素位置arrLocation为0
		int left = m;
		int arrLocation = 0;
		
		// 循环数组,报数,剩余人数为1时退出
		while (left > 1) {
			if (arr[arrLocation] == 0) {
				// 数组位置为0时,报数
				speaker++;
				
				// 报到n时,报数器speaker置0
				// 数组位置值修改为1,剩余人数left减1
				if (speaker == n) {
					speaker = 0;
					arr[arrLocation] = 1;
					left--;
				}
				
				// 完成当次报数后,位置加1
				// 若数组位置值为数组长度时,说明到了数组末尾,将位置置0,开启新一轮的循环
				arrLocation++;
				if (arrLocation == m) {
					arrLocation = 0;
				}
			} else {
				// 数组位置不为0时,直接移动位置;
				// 若数组位置值为数组长度时,说明到了数组末尾,将位置置0,开启新一轮的循环
				arrLocation++;
				if (arrLocation == m) {
					arrLocation = 0;
				}
			}
		}
		
		for (int i=0; i<arr.length; i++) {
			if (arr[i] == 0) {
				System.out.println(i+1);
			}
		}
	}

上記の実装は最後に残った人です。トピックがわずかに変更された場合、残りの1人はn未満に変更され、while条件はleft> nに変更されます。

リストの実装

リストの実装は配列の実装と似ていますが、次のように少し異なります。

	/**
	 * 报数退出
	 * @param m 总人数
	 * @param n 报到n时退出
	 */
	public static void reportNumberList(int m, int n) {
		// 初始化list,list置每个位置初始值
		List<Integer> list = new ArrayList<>();
		for (int i=0; i<m; i++) {
			list.add(i+1);
		}
		
		// 初始化报数器speaker为0
		int speaker = 0;
		
		// 初始化list元素位置arrLocation为0
		int arrLocation = 0;
		
		// 循环list,报数,剩余1个人时退出
		while (list.size() > 1) {
			// 报数
			// 同数组实现不同,list中将报到为n的位置直接删除了
			speaker++;
			
			// 报到n时,报数器speaker置0
			// 删除list该位置的元素
			if (speaker == n) {
				speaker = 0;
				list.remove(arrLocation);
				
				// 若数组位置值为list长度,说明到了list末尾,将位置置0,开启一次新的循环
				if (arrLocation == list.size()) {
					arrLocation = 0;
				}
			} else {
				// 完成当次报数后,位置加1
				// 若数组位置值为list长度,说明到了list末尾,将位置置0,开启一次新的循环
				arrLocation++;
				if (arrLocation == list.size()) {
					arrLocation = 0;
				}
			}
		}
		
		System.out.println(list.get(0));
	}

コードテスト

	public static void main(String[] args) {
		reportNumber(10, 3);
		reportNumberList(10, 3);
		
		reportNumber(100, 3);
		reportNumberList(100, 3);
	}

4
4
91
91

テストでは、10人の場合、最後に残っている人の位置は4であり、問​​題分析と同じです。100人の場合、最後に残っている人の位置は91です。

 

おすすめ

転載: blog.csdn.net/magi1201/article/details/114604586