1.定义
给出正整数n,表示一个从1~n的环,再给出一个报数m,开始从1开始报数,报到m时,从环中去掉这个数,下个位置继续从1开始报数,直到整个环没有数字为止,依次输出这些数。
2.思路
解决这种环形问题,我们首先想到的是循环结构体,这里采用循环单链表来解决,记录前驱节点和当前节点位置,当当前节点p的报数等于m时,利用前驱节点删除它,用一个count计数,当删除的数为n时,让当前节点为空,则退出了循环。
这里给出一个n为8的环。
3.代码实现:
import java.util.Scanner;
//定义节点信息
class Node{
int data;
Node next;
public Node(int data){ this.data=data;}
}
class Solution{
//用单循环链表来创建约塞夫环
public void CreateLink(int n,Node h,Node r){
for (int i = 1; i <=n ; i++) {
Node p=new Node(i);
r.next=p;
r=r.next;
}
r.next=h.next;
}
//约塞夫环解决方法
public int[] way(int n,int m,Node h,Node r){
Node p=h.next,pre=r; //p为当前节点,pre为前驱节点
int k=0,count=0; //k为当前节点报数,count为删除节点数
int res[]=new int[n]; //用数组来保存结果
while (p!=null){
k++; //当前报数
if (k==m){ //等于最大报数时,删除节点
res[count++]=p.data;
if (count==n){ //退出循环操作
p=null;
continue;
}
pre.next=p.next; //删除节点
p=p.next;
k=0; //下个节点从新开始计数
}
else { //不符合条件,后移
p=p.next;
pre=pre.next;
}
}
return res;
}
}
public class Joseph_circle {
public static void main(String args[]){
Solution solution=new Solution();
Scanner sc=new Scanner(System.in);
int n=sc.nextInt(); //节点个数
int m=sc.nextInt(); //报数最大值
Node h=new Node(0); //带头结点的链表
Node r=h;
solution.CreateLink(n,h,r);
int res[]=solution.way(n,m,h,r);
for (int k:res) {
System.out.println(k);
}
}
}
4.实验结果
输入n=8,m=3的结果