• 约瑟夫问题(丢手绢问题)


    /**
     * TODO 约瑟夫问题(丢手绢问题)
     * 
     * @author kakaluote
     * @date 2021年8月30日 下午3:57:05
     */
    public class Josepfu {
    
    	public static void main(String[] args) {
    		
    		CircleSingleLinkedList singleLinkedList = new CircleSingleLinkedList();
    		singleLinkedList.addBoy(5);
    //		singleLinkedList.showBoy();
    		singleLinkedList.countBoy(1, 2, 5);
    	}
    }
    
    //创建一个环形的单向链表
    class CircleSingleLinkedList {
    	private Boy first = null;
    	
    	//添加小孩节点,形成环形链表
    	public void addBoy(int nums){
    		if(nums < 1){
    			throw new RuntimeException("nums 的值非法。");
    		}
    		//辅助变量,帮助我们构建环形链表
    		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;
    			}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){
    			throw new RuntimeException("参数输入有误");
    		}
    		Boy helper = first;
    		//helper 指向环形链表的最后一个节点
    		while(true){
    			if(helper.getNext() == first){
    				break;
    			}
    			helper = helper.getNext();
    		}
    		//小孩报数前,先让first 和 helper 移动 k-1 次
    		for (int i = 0; i < startNo - 1; i++) {
    			first = first.getNext();
    			helper = helper.getNext();
    		}
    		//当小孩报数时,让first 和 helper指针 同时移动m-1次,然后出圈
    		//这里是一个循环操作
    		while (true) {
    			//说明圈中只有一个节点
    			if(helper == first){
    				break;
    			}
    			//让first 和 helper指针 同时移countNum-1次
    			for (int i = 0; i < countNum - 1; i++) {
    				first = first.getNext();
    				helper = helper.getNext();
    			}
    			//这时first指向的节点,就是要出圈的小孩节点
    			System.out.printf("小孩 %d 出圈 
    ",first.getNo());
    			//这时将first指向的小孩节点出圈
    			//first移动到first的下一个节点,也就是出圈孩子的下一个节点
    			first = first.getNext();
    			//helper 的next 指向新的first
    			helper.setNext(first);
    		}
    		System.out.printf("最后留在圈中的小孩编号 %d 
    ",first.getNo());
    	}
    	
    	//遍历当前环形链表
    	public void showBoy(){
    		if(first == null){
    			System.out.println("链表为空");
    			return;
    		}
    		//因为first不能动,需要一个辅助变量完成遍历
    		Boy curBoy = first;
    		while(true){
    			System.out.printf("小孩的编号 %d 
    ",curBoy.getNo());
    			//说明已经遍历完毕
    			if(curBoy.getNext() == first){
    				break;
    			}
    			//curBoy 后移
    			curBoy = curBoy.getNext();
    		}
    	}
    }
    
    class Boy{
    	private int no;
    	private Boy next;
    	public Boy(int no) {
    		super();
    		this.no = no;
    	}
    	public int getNo() {
    		return no;
    	}
    	public void setNo(int no) {
    		this.no = no;
    	}
    	public Boy getNext() {
    		return next;
    	}
    	public void setNext(Boy next) {
    		this.next = next;
    	}
    }
    
  • 相关阅读:
    Magisk+Xposed+Root switch+Pokémon GO
    [数据库连接池] Java数据库连接池--DBCP浅析.
    [C#反射]C#中的反射解析及使用.
    [Java工具]Java常用在线工具集合.
    [Java拾遗五]使用Session防止表单重复提交
    [Java拾遗四]JavaWeb基础之Servlet_Request&&Response
    [Java拾遗三]JavaWeb基础之Servlet
    [Java拾遗二]Tomact及Http 部分总结.
    [Java拾遗一] XML的书写规范与解析.
    [数据库操作]Java中的JDBC的使用方法.
  • 原文地址:https://www.cnblogs.com/kaka-qiqi/p/15217657.html
Copyright © 2020-2023  润新知