思路分析:
- 需要创建一个辅助指针temp,事先应该指向环形链表的最后
- 报数之前,应该将first和temp移动k-1次
- 当报数时,first和temp同时移动,移动m-1次(m为报数次数)
- 这时就可以将first指的出圈,原来first指向的节点就没有任何引用了,就"出圈"了
- first=first.next
- temp.next=first
package com.ran;
public class hello {
public static void main(String[] args) {
Lianbiao lianbiao=new Lianbiao();
lianbiao.zeng(5);
lianbiao.cha();
lianbiao.chuquan(1,2,5);
}
}
class Lianbiao{
//创建一个first节点 当前没有编号
private HeroNode first=null;
//startno第几个开始数数
//countno 数几下
//num 最初有多少个人
//根据输入计算出出圈顺序
public void chuquan(int startno,int countno,int num){
if(first==null||startno<1||startno>num){
System.out.println("cuowu");
return;
}
HeroNode temp=first;
//应该先将辅助指针指向最后一个位置
while (true){
if(temp.next==first){
break;
}
temp=temp.next;
}
//先移动到报数那
for(int i=0;i<startno-1;i++){
first=first.next;
temp=temp.next;
}
//开始报数
//这里是一个循环操作
while (true){
if(temp==first){
System.out.println("只有一个节点");
break;
}
for(int i=0;i<countno-1;i++){
first=first.next;
temp=temp.next;
}
//这是first指的就是出圈的
System.out.printf("出圈%d",first.no);
first=first.next;
temp.next=first;
}
System.out.println("最后留在圈中的"+first.no);
}
public void zeng(int num){
//做num做一个校验
if(num<1){
System.out.println("不正确");
return;
}
HeroNode temp=null;//辅助指针,帮助构建环形链表
//for循环创建环形链表
for(int i=1;i<=num;i++){
//根据编号创建小孩节点
HeroNode heroNode=new HeroNode(i);
//如果是第一个小孩
if(i==1){
first=heroNode;
first.setNext(first);//构成环
temp=first;
}else {
temp.setNext(heroNode);
heroNode.setNext(first);
temp=heroNode;
}
}
}
public void cha(){
if(first==null){
System.out.println("空");
return;
}
HeroNode temp=first;
while (true){
System.out.println("编号:"+temp.getNo());
if(temp.getNext()==first){
break;
}
temp=temp.getNext();
}
}
}
//创建双向链表
class HeroNode{
public int no;
public HeroNode next;
public int getNo() {
return no;
}
public void setNo(int no) {
this.no = no;
}
public HeroNode getNext() {
return next;
}
public void setNext(HeroNode next) {
this.next = next;
}
public HeroNode(int no) {
this.no = no;
}
}
代码运行效果如下: