Report the number and exit the game

Topic information

There are n people in a circle, arranged in order. Start counting from the first person (from 1 to 3). Anyone who reports to 3 will withdraw from the circle and ask which person is the original number left at the end.

answer

This topic is relatively classic, and it is also known as the Joseph ring problem. Friends who are interested can search for Joseph ring.

Make a simple example, take 10 people to report the number, and then exit

Array position compared to 10 people reported exit problems

From the above example, you can see:

  1. Define the initial array, the initial value of the array position is 0
  2. The counter only reports the number where the value is 0
  3. When the counter reports to 3, modify the position value to 1, and the remaining number of people is reduced by 1
  4. Announce the number in a loop, exit when the remaining number is 1
  5. When the array loops to the end, the array position is set to 0
  6. If the value of the looped position is not 0, the position will be moved after adding 1
  7. When the loop exits, print the array and output the position of 0

coding

Array implementation

According to the analysis of the above problem, use the array to realize the algorithm

	/**
	 * 报数退出
	 * @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);
			}
		}
	}

The above implementation is the last remaining person. If the topic is slightly modified, the remaining 1 person is modified to be less than n, and then left> 1 in the while condition is modified to left> n.

list implementation

The implementation of the list is similar to that of the array, but slightly different, as follows

	/**
	 * 报数退出
	 * @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));
	}

Code test

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

4
4
91
91

The test found that when there are 10 people, the last remaining person position is 4, which is the same as the problem solution analysis; when there are 100 people, the last remaining person position is 91

 

Guess you like

Origin blog.csdn.net/magi1201/article/details/114604586