josepfu

josepfu问题

Josephu 问题为:设编号为 1,2,… n 的 n 个人围坐一圈,约定编号为 k(1<=k<=n)的人从 1 开始报数,数到 m 的那个人出列,它的下一位又从 1 开始报数,数到 m 的那个人又出列,依次类推,直到所有人出列为止,由此 产生一个出队编号的序列。

  • 思路分析:
    两个相连的数据之中取出一个元素。
    1->2->3->4->5
    2->4->1->5->3

  • 实现思路:
    在一个队列之中,同时放入两个指针,并且取出掉第二个指针所指的元素。
    两个指针分别为:curboy,helper

代码实现

建立一个环形单向链表

class CircleSingleLinkedList {
 // 创建一个 first 节点,当前没有编号
 private Boy first = null;
 // 添加小孩节点,构建成一个环形的链表 
 public void addBoy(int nums) { 
 // nums 做一个数据校验 if (nums < 1) { System.out.println("nums 的值不正确"); 
 return; 
 }
建立环形
Boy curBoy=null;
for(int i=1;i<=nums;i++){
	Boy boy = new Boy(i); // 如果是第一个小孩 
	if (i == 1) {
	 first = boy; 
	first.setNext(first); // 构成环 
	curBoy = first; // 让 curBoy 指向第一个小孩 
	} else {
	 curBoy.setNext(boy);
	boy.setNext(first);
	curBoy = boy; 
				}
		 }
	}

计算小孩出圈的顺序

/**** @param startNo  * 表示从第几个小孩开始数数 
* @param countNum  * 表示数几下 
* * @param nums   * 表示最初有多少小孩在圈中 
* */ 
public void countBoy(int startNo, int countNum, int nums) {
 // 先对数据进行校验
  if (first == null || startNo < 1 || startNo > nums) {
  		System.out.println("参数输入有误, 请重新输入");
   		return; 
    	}
Boy helper = first; 
// 需求创建一个辅助指针(变量) helper , 事先应该指向环形链表的最后这个节点
 while (true) { 
 	if (helper.getNext() == first) {
 	 // 说明 helper 指向最后小孩节点 
 	 	break; }
 	 	helper = helper.getNext(); }
 	 	//小孩报数前,先让 first 和 helper 移动 k - 1 次
 	 	//为了让指针运动到,想要移除的元素上
 	 for(int j = 0; j < startNo - 1; j++) { 
 	 	  first = first.getNext();
 	 	  helper = helper.getNext();
 	 	  	 }
 	 	  	 //当小孩报数时,让 first 和 helper 指针同时 的移动 m - 1 次, 然后出圈
 	 	  	  //这里是一个循环操作,知道圈中只有一个节点
 	 	 while(true) { 
 	 	 if(helper == first) { 
 	 	 //说明圈中只有一个节点
 	 	  		break;
 	 	   }//让 first 和 helper 指针同时 的移动countNum - 1 
 	 	   for(int j = 0; j < countNum - 1; j++) { 
 	 	   first = first.getNext(); 
 	 	   helper = helper.getNext(); 
 	 	   }
    }
  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值