华为某年的一个机考题:计算最后一个出列者的编号

这篇博客介绍了华为某年机考中的一道编程题,涉及竞争者报数问题。作者通过齿轮模型来抽象问题,并提供了解题思路和具体实现代码,强调了逻辑思维、问题抽象和基础编码能力的重要性。最终,通过模拟报数过程,当只剩下一个竞争者时,输出其编号。
摘要由CSDN通过智能技术生成
描述: 现在有n个竞争者围坐一圈,争夺一个很有吸引力的工作(年薪100w $)。假设这些人编号1,2,。。。,n。第一次从1开始报数,数到m(m>0)的那个人出列,它的下一位又从1开始报数,数到m的那个人又出列。以此类推,直到所有人出列为止。老板说最后一个出列的人将获得这份工作。    
如果你也想竞争这份工作,那么你会坐着哪个位置上?   


实现一个函数,当老板告诉你n和m时,返回得到工作的那个人的编号。  
  
运行时间限制: 无限制  
内存限制: 无限制  


输入: 竞争者人数,报数    
输出: 最后出列的竞争者的编号。异常则返回 -1。


样例输入: 10,10  

样例输出: 8 

思路:个人认为该题主要考察答题者的逻辑思维、现实问题抽象成编程模型以及基础编码能力,当你把逻辑理顺了后,其实只需要很短的一段代码就实现了。回到题目上,此题涉及到竞争者报数,当报到m的时候,删除该竞争者,依次循环。抽象出来,可以理解为齿轮问题,一个周长为n(齿尖编号分别为1-n)的齿轮带动一个周长为m(齿尖编号为1-m)的齿轮旋转,每当遇到编号为m的齿尖的时候,周长为n的齿轮去掉对应的齿尖,齿轮变小,以此类推,直到只剩下最后一个齿尖(从微观上来看,此时齿轮为一个圆点),得到该齿尖的编号。于是我们设置两个指针,分别指向两个齿轮接触点对应的竞争者编号和报数的数值,报数每循环一轮(1-m)竞争者少一个,直到竞争者剩下最后一个,得到编号。

图形表示:


具体实现代码(带注释):

import java.util.LinkedList;
import java.util.Scanner;

/**  
 * Package: com.properties.test  
 *  
 * File: GetCompetitorNum.java   
 *  
 * Copyright @ 2015 Corpration Name  
 *   
 */
public class GetCompetitorNum {

	public static int getNum(int n,int m){
		int count = 0;//用于记录报数的数字,在1到m之间循环
		int temp = 0; //用于记录报数时所指向的竞争者,当count为m的时候,删除此时temp所指向的竞争者
		LinkedList<Integer> list = new LinkedList<>();//用整数模拟每个竞争者,编号为1->n
		for (int i = 1; i < n + 1; i++) {
			list.add(i);  //将n个竞争者放入到list中
		}
		while(list.size() > 1){   //循环结束条件为:当list中还剩下一个值得时候,即竞争者还剩一个
			if(temp == list.size()){ 
				temp = 0;   //当temp的值等于list的当前所剩竞争者数量的时候,重置为0
			}
			count++;
			temp++;
			if(count == m){
				list.remove(temp-1);  //报数到m,删除此时temp所指向的竞争者
				count = 0;            //删除后,报数重置为0,下一轮报数从1开始
				temp = temp - 1;      //删除后,list少一个竞争者,此时temp所指向的是删除前的下一个竞争者,所以回退一个值
									  //如果不回退,则下一轮就跳过被删除竞争者的后面一个竞争者,就等于报数跳过了这个人
			}
			
		}
		return list.get(0);  //最后返回剩下的最后一个竞争者
	}
	public static void main(String[] args){
		Scanner scanner = new Scanner(System.in);
		try {
			String str = scanner.nextLine();
			int n = Integer.valueOf(str.split(",")[0]);
			int m = Integer.valueOf(str.split(",")[1]);
			int output = getNum(n, m);
			System.out.println(output);
		} catch (Exception e) {
			System.out.println(-1);
		}
		scanner.close();
		
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值