公司招聘问题(约瑟夫环升级版)

题目:

某公司招聘,有n个人入围,HR在黑板上依次写下m个正整数A1、A2、……、Am,然后让这n个人围成一个 圈,并按照顺时针顺序为他们编号0、1、2、……、n-1。录取规则是:
第一轮从0号的人开始,取用黑板上的第1个数字,也就是A1黑板上的数字按次序循环取用,即如果某轮用了第m个,则下一轮需要用第1个;如果某轮用到第k个,则下轮需要用第k+1个(k<m)
每一轮按照黑板上的次序取用到一个数字Ax,淘汰掉从当前轮到的人开始按照顺时针顺序数到的第Ax个人,下一轮开始时轮到的人即为被淘汰掉的人的顺时针顺序下一个人 被淘汰的人直接回家,所以不会被后续轮次计数时数到经过n-1轮后,剩下的最后1人被录取所以最后被录取的人的编号与(n,m,A1,A2,……,Am)相关。
输入描述:
第一行是一个正整数N,表示有N组参数从第二行开始,每行有若干个正整数,依次存放n、m、A1、……、Am,一共有N行,也就是上面的N组参数。
输出描述:
输出有N行,每行对应相应的那组参数确定的录取之人的编号示例1:
输入
1
4 2 3 1
输出
1

样例解释
样例里只有 1 组测试数据,说的是有 4 人入围(编号 0∼3)。

黑板上依次写下 2 个数字:3、1,那么:

第一轮:当前轮到 0 号,数到数字 3,顺时针数第 3 个人是 2 号,所以淘汰 2 号,下一轮从 3 号开始,目前剩余:0、1、3;

第二轮:当前数到 3 号,取到数字 1,顺时针数第 1 个人是 3 号,所以淘汰 3 号,下一轮从 0 号开始,目前剩余:0、1;

第三轮:当前轮到 0 号,循环取到数字 3,顺时针数第 3 个人是 0 号,所以淘汰 0 号,最后只剩下 1 号,所以录取 1 号,输出 1;

解法:

要清楚三个递推公式

1 没人出局前报号与人员编号对应关系:id = (num-1)%i + 1

id:每个人的id标识

num:每个人报的数,从1,2,3……n

i:一共有i个结点

函数图像大致为:

2 出局一个人后报号与人员编号对应关系:id = (num-1+s)%i + 1

s:出局的人的id编号

此时函数图像有实际意义:

纵坐标:出局一人前,在旧的圈内报数的值

横坐标:出局一人后,在新的圈内报数的值

函数图像大致为:

从图像分析,出局后的报数图像为出去前报数图像向左平移s个单位

3 出局人编号和选择的编号的关系:s = (m-1)%i+1

m:选择的编号

图像同函数1,如选择报数为1(m)的人出局,则编号1(s)出局,仨人一循环(i=3),则编号4(s)的人也出局。

最终化简递推式:

id = (num-1+(m-1)%i+1)%i + 1 = (num+m-1)%i + 1

在老圈子报数 = (新圈报数 + 由老圈变新圈选择的报数规则 - 1)%老圈人数 +1

Coding

	public static Node josephusKill2(Node head, int m) {
		if (head == null || head.next == head || m < 1) {
			return head;
		}
		Node cur = head.next;
		int tmp = 1; // tmp -> list size
		//寻找头节点
		while (cur != head) {
			tmp++;
			cur = cur.next;
		}
		tmp = getLive(tmp, m); // tmp -> service node position
		//寻找存活结点
		while (--tmp != 0) {
			head = head.next;
		}
		head.next = head;
		return head;
	}

	public static int getLive(int i, int m) {
		if (i == 1) {
			return 1;
		}
		return (getLive(i - 1, m) + m - 1) % i + 1;
	}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值