约瑟夫/约瑟夫环问题

Josephu

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

基本思路:

//环形链表的创建

1.首先构建一个单向的环形链表

        先创建一个头节点和一个辅助节点,让辅助节点去指向每一个新增的节点

        每新增一个节点,该节点的下一个指向必须是头节点,这样才可以形成闭环

2.遍历环形链表

        使用辅助节点curboy=first去遍历链表,当curboy.getnext()==first即结束遍历

//小孩出圈基本思路

/**
     * start:表示从第几个小孩开始数
     * count:表示小孩数几下
     * nums:表示小孩的个数
     */

1.创建一个辅助节点helper跟在first节点的后面

2.让helper和first分别走(start-1)步,即站在起点开始数数

3.让helper和first分别走(count-1)步,数几下就走几步,注意first本身算一步,所以count要-1

4.数完步数后出圈,first首先指向下一个节点:first=first.getnext(),然后helper指向first节点:helper.setnext(first)

代码实现:

package linkedlist;

public class Josepfu {
	public static void main(String[] args) {
		CircleLinkedList linkedlist= new CircleLinkedList();
		linkedlist.add(5);
		linkedlist.show();
		linkedlist.counts(1, 2, 5);
	}
}
//创建单项环形链表
class CircleLinkedList{
	//链表头节点
	private Boy first=null;
	//辅助节点,代替头节点遍历链表
	Boy curboy=null;
	//添加节点
	public void add(int nums){
		if(nums<1){
			System.out.println("输入的数值不正确");
			return ;
		}
		for(int i=1;i<=nums;i++){
			//创建新节点
			Boy boy=new Boy(i);
			if(i==1){
				first=boy;
				first.setNext(first);
				curboy=first;
			}else{
				curboy.setNext(boy);
				boy.setNext(first);
				curboy=boy;
			}
		}
	}
	public void show(){
		if(first==null){
			System.out.println("链表为空");
		}
		curboy=first;
		while(curboy.getNext()!=first){
			System.out.println("小孩的编号为:"+curboy.getNum());
			curboy=curboy.getNext();
		}
		System.out.println("小孩的编号为:"+curboy.getNum());
	}
	/**
	 * start:表示从第几个小孩开始数
	 * count:表示小孩数几下
	 * nums:表示小孩的个数
	 */
	public void counts(int start,int count,int nums){
		//数据校验
		if(start<1||start>nums){
			return ;
		}
		Boy helper=first;
		while(helper.getNext()!=first){
			helper=helper.getNext();
		}
		for(int i=0;i<start-1;i++){
			first=first.getNext();
			helper=helper.getNext();
		}
		while(true){
			if(helper==first){
				break;
			}
			for(int i=0;i<count-1;i++){
				first=first.getNext();
				helper=helper.getNext();
			}
			System.out.println("出圈小孩的编号为:"+first.getNum());
			first=first.getNext();
			helper.setNext(first);
		}
		System.out.println("最后留在圈内的小孩编号是:"+first.getNum());
	}
}
//创建一个Boy实例,表示一个小孩的节点
class Boy{
	private int num;
	private Boy next;
	public Boy(int num){
		this.num=num;
	}
	public int getNum() {
		return num;
	}
	public void setNum(int num) {
		this.num = num;
	}
	public Boy getNext() {
		return next;
	}
	public void setNext(Boy next) {
		this.next = next;
	}
	
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值