报数退出【笔试编程题】

    昨天晚上笔试中的题。和大一学C语言遇到过的引约瑟夫问题(猴子选大王)一样的哈哈。以前用数组做的,现在用队列啦,在进步哦哈哈~

    题目要求:有n个人围成一圈,顺序排号。从第一个人开始报数(从1到m报数),凡报到m的人退出圈子,问最后留下的是原来第几号的那位。

package daily;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Scanner;

public class Main {
	private static Scanner scanner = null;
	static {
		scanner = new Scanner(System.in);
	}

	public static void main(String[] args) {
		System.out.println("请输入一共有多少人:");
		int a = scanner.nextInt();
		Long atime = System.currentTimeMillis();
		System.out.println(new Main().getNum(a));
		Long btime = System.currentTimeMillis();
		Long ctime = btime - atime;
		System.out.println("使用的时间为:" + ctime + "毫秒.");
	}

	/**
	 * 题目要求:有n个人围成一圈,顺序排号。从第一个人开始报数(从1到3报数),凡报到3的 人退出圈子,问最后留下的是原来第几号的那位。
	 * 
	 * @param n
	 * @return
	 */
	public String getNum(int n) {
		LinkedList> linkedList = new LinkedList>();
		System.out.println("请输入要报的数:");
		int b = scanner.nextInt();
		// 初始化将数据保存在队列中
		for (int i = 1; i <= n; i++) {
			Map map = new HashMap();
			int value = i % b;
			map.put(String.valueOf(i), value);
			linkedList.add(map);
		}
		int size = linkedList.size();
		while (size > 1) {

			// 挑选出报数为b的数据
			for (int i = 0; i < size; i++) {
				Map map = linkedList.poll();
				String key = (String) map.keySet().toArray()[0];
				if (map.get(key) != 0) {
					linkedList.add(map);
				}
			}

			size = linkedList.size();

			// 将队列中的元素重新赋值排序
			Map lastMap = linkedList.getLast();
			String lastKey = (String) lastMap.keySet().toArray()[0];
			int lastValue = lastMap.get(lastKey);
			int firstValue = (lastValue + 1) % b;
			for (int i = 0; i < size; i++) {
				Map map = linkedList.poll();
				String key = (String) map.keySet().toArray()[0];
				map.put(key, firstValue);
				linkedList.add(map);
				firstValue = (++firstValue) % b;
			}

		}

		String resultKey = (String) linkedList.peek().keySet().toArray()[0];
		System.out.print("最后留下来的是:");
		return resultKey;
	}
}

报数退出【笔试编程题】_第1张图片

 

既然都提到猴子选大王了,那就回顾一下吧~

 【问题描述】:M只猴子要选大王,选举办法如下:所有猴子按1-M编号围坐一圈,从1号开始按顺序1,2,,,K报数,凡报到K的猴子退出到圈外,如此循环报数,直到圈内只剩下一只猴子时,这只猴子就是大王。M和K由输入文件提供,要求在输出文件中打印出最后剩下的猴子的编号。数据规模(M<=1000,K<=10)

【输入文件】

输入文件m.in 的第1 行,为两个正整数,用一个空格隔开:

M K

【输出文件】

输出文件m.out 只有一个正整数,输出最后一个猴子的编号

【输入样例】

7 3

【输出样例】

4

 分析:

我们可以假设猴子就位的状态用1表示,把猴子离开的状态用0表示。那么我们就可以用一个a[M]的数组来存放M个猴子是否就位的状态。我们可以一边报数一边遍历该数组,每遇到第K个1时,就把当前位置的1变为0,表示当前位置的猴子已经出局了。一直循环遍历到我们的状态数组只有一个1的时候,这个存放1的数组下标再加上1(因为数组下标是由0开始的,所以要加1)即为选出的大王的编号。想法很简单,现在关键的问题是如何解决当报数到第M个猴子的时候如何使得下一个报数重新回到第1个猴子处,也就是如何使用一维数组来解决环型问题的求解技巧。大家想一下当我们的猴子围成圈坐的时候,问题其实由简单的一维数组变成了首尾相接的环型数组,也就是我们数据结构中的环型队列。假设p为当前数组某一元素的下标,对于一维数组来说,我们只要p++就可以移动到下一个元素的位置上。那么当p=M时,如果我们直接使用p++的话,p的值就超出了a[M]数组的最大长度,我们想要的是p++之后等于0。那么如何实现呢?解决环型数组循环遍历元素的方法:对于环型数组移动下标时,我们如果每次在p++之后再加上p=p%M的话就能解决先前遇到的越界的问题。下标变量p也就可以周而复始的在a[M]中顺时针地循环移动了.

#include 

int main()

{

  

    int n,i;

    int n1=0;

    int p=0;

    int NumOfKing;

    int M,K;

    int a[1000];

    FILE *fp1,*fp2;

    if((fp1=fopen("m.in","r"))==NULL)

    {

      printf("cann't open file!\n");

      return 0;

    }

    fscanf(fp1,"%d%d",&M,&K);     

    n=M;

    for(int i=0;i1)

    {

       while(n1

 

你可能感兴趣的:(面试题)