原题链接:[编程入门]报数问题
解题思路:
这道题明显就是一个约瑟夫环的问题,只不过就是简化了,给了一个固定的数而已
思路如下:
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、信息学奥赛的必学课程:算法竞赛课入门课程
手把手讲解近五年真题的蓝桥杯辅导课程
发表评论 取消回复