问题:例如有n个人坐在圆桌上,每个人有自己的编号,分别从1开始到n号,最后由n号指向1号形成闭环。从第1号开始依次报数,n号下一个人即1号报n+1号(例如n=10,则10号下一个人报数11)以此类推,凡遇到报数为k的倍数时,将此人踢出圆桌,最终圈内剩下1人,求最后这个人是几号?
编程思路:在圆桌上的所有人形成了一个闭环的圆形,每个人都与上一个及下一个人相关联,最后一个人与第一个相关联,可以使用链表来表示:
编写“人”的对象
public class People {
private int id;//记录每个人的自身编号
private People prev;//关联的上一个人
public int getId() {
return id;
}
public People getPrev() {
return prev;
}
public People getNext() {
return next;
}
private People next;//关联的下一个人
public People(int id)
{
this.id=id;
}
//处理每个人相关联的方法
//参数为要关联的下一个人
public void linkNext(People next)
{
this.next=next;
this.next.prev=this;//将下一个人的上一个人关联为this本身对象
}
}
编写圆桌对象:
public class Circle {
public People getCurrent() {
return current;
}
private People current;//记录正在处理的当前对象
private int count;//圆中人员的数量
public Circle(int count)
{
if(count<1)
{
return;
}
this.count=count;
People first=new People(1);//先创建第一个人 并编号为1
current=first;
for(int i=2;i<=count;i++)//从第二个人开始循环创建对象,一直到count人,
{
current.linkNext(new People(i));//调用linkNext()方法为current关联上下对象
current=current.getNext();//将下一个对象作为当前对象current接着去循环关联。
}
//最后创建关联所有人员后,current目前内容为最后一个人,将最后一个人与第一个进行关联
current.linkNext(first);
}
public Circle numberOff(int k)
{
int num=0;//定义从第几个人开始报数
while(count>1)
{
num++;//开始报数
current= current.getNext();//之前创建人员时,current内容为最后一个人,通过getNext()将current对象赋值为第一个人
if(num%k==0)//如果为true则当前报数内容为k的倍数
{
current.getPrev().linkNext(current.getNext());//将current的上一个人指向下一个人,表示删除当前的人
current=current.getPrev();//将current变为要删除的上一个,接着从循环开始处进行报数。
count--;
}
}
return this;//最后返回Circle对象,形成方法链编程风格。
}
}
最后测试类:
public class Main {
public static void main(String[] args) {
//new Circle(1000)创建1000个人,numberOff(7)遇到7的倍数踢出
System.out.println(new Circle(1000).numberOff(7).getCurrent().getId());
}
}
程序运行结果:
学习思路来源:https://v.douyin.com/Nd63tL9/