念心卓


私信TA

用户名:uq_80412005216

访问量:2758

签 名:

人不自渡,天也难助

等  级
排  名 1587
经  验 2766
参赛次数 2
文章发表 24
年  龄 0
在职情况 学生
学  校 哔哩哔哩大学
专  业 软件工程

  自我简介:

解题思路:


这道题明显就是一个约瑟夫环的问题,只不过就是简化了,给了一个固定的数而已


思路如下:


1. 需要创建一个单向的循环链表(怎么创建这里我就不多说了)


2. 解决约瑟夫环问题的思路:


 2.1 需要创建一个辅助指针(变量)temp,事先应该指向环形链表的最后一个节点


 2.2 开始报数前,先让first和temp移动k-1次,也就是先让first指向当前要报数的人,temp指向first的上一个节点。


 2.3 当开始报数时,让first和temp同时移动m-1次


 2.4 这时就将first指向的节点出圈


 2.5 first= first.next


 2.6 temp.next = first


 2.7 原先first指向的节点就没有任何的引用,就会被垃圾回收机制回收

 注意事项:

 1. 有链表的基础,懂循环链表

参考代码:

    public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		int n = scanner.nextInt();//输入初始人数n
		ManageCircleNode manageCircleNode = new ManageCircleNode(); 
		manageCircleNode.addNode(n);
		//manageCircleNode.showList();
		manageCircleNode.order(1, 3, n);
	}
//1.首先创建节点
class CircleNode{
	private int no;//表示编号
	private CircleNode next;
	public CircleNode(int no) {
		this.no = no;
	}
	public int getNo() {
		return no;
	}
	public void setNo(int no) {
		this.no = no;
	}
	public CircleNode getNext() {
		return next;
	}
	public void setNext(CircleNode next) {
		this.next = next;
	}
	
}
//2.创建节点管理类
class ManageCircleNode{
	CircleNode first = null;
	CircleNode curFomerNode = null;//表示当前节点的指针,用来指向新创建节点的前一个节点
	CircleNode curNode = null;//用来指向新创建的节点。
	public void addNode(int nums) {//nums:参与的人数
		for(int i = 1; i <= nums; i++) {
			CircleNode newNode = new CircleNode(i);
			if(i == 1) {
				//如果是第一个节点,那么first就指向他,之后不能动
				first = newNode;
				//让自己成为一个环
				first.setNext(first);
				curFomerNode = first;//指向第一个节点
			}
			//如果不是第一个,执行以下操作
			curFomerNode.setNext(newNode);
			curNode = newNode;
			curFomerNode = curNode;//向下移动
			curNode.setNext(first);//成为一个环
		}
	}
	//求出圈的顺序
	/**
	 * 
	 * @param k 表示从编号k个人开始数
	 * @param m 表示数到m号(及是m号的人出列)
	 * @param nums
	 */
	public void order(int k,int m,int nums) {
		//首先先让一个辅助变量指向first的最后一个节点,也就是first的上一个节点
		CircleNode temp = first;
		while(true) {
			if(temp.getNext() == first) {
				break;
			}
			temp = temp.getNext();
		}
		//在开始报数之前,先将temp和first移动k-1次
		for(int i = 1; i <= k-1 ; i++) {
			temp = temp.getNext();
			first = first.getNext();
		}
		//开始报数时,让first和temp同时移动m-1次,然后出圈
		while(true) {
			if(temp == first) {
				//此时圈中只有一个节点,出圈
				break;
			}
			for(int i = 1; i <= m-1; i++) {//first指的节点就是要出圈的
				temp = temp.getNext();
				first = first.getNext();
			}
			//System.out.printf("编号为%d的人出圈\n",first.getNo());
			first = first.getNext();//指向下一个
			temp.setNext(first);
		}
		System.out.println(temp.getNo());//最后一个出圈的是编号的节点
	}
	//测试方法:遍历单向循环链表
	public void showList() {
		if(first == null) {
			System.out.println("链表为空~~~");
			return;
		}
		//遍历节点;当遇到curFormerNode.getNext() == first时结束
		curFomerNode = first;//指向第一个节点
		while(true) {
			System.out.println("圈中的编号为:"+curFomerNode.getNo());
			if(curFomerNode.getNext() == first) {
				break;
			}
			curFomerNode = curFomerNode.getNext();
		}
	}
}




 

0.0分

0 人评分

  评论区

  • «
  • »