原题链接:[编程入门]报数问题
解题思路:
这道题明显就是一个约瑟夫环的问题,只不过就是简化了,给了一个固定的数而已
思路如下:
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 人评分
C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:
一点编程也不会写的:零基础C语言学练课程
解决困扰你多年的C语言疑难杂症特性的C语言进阶课程
从零到写出一个爬虫的Python编程课程
只会语法写不出代码?手把手带你写100个编程真题的编程百练课程
信息学奥赛或C++选手的 必学C++课程
蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程
手把手讲解近五年真题的蓝桥杯辅导课程
发表评论 取消回复