循环链表(约瑟夫环)思路及实现
循环链表
单链表的尾节点指向首节点,即可构成循环链表
约瑟夫环
约瑟夫问题:有 N 个人围成一圈,每个人都有一个编号,编号由入圈的顺序决定,第一个入圈的人编号为 1,最后一个为 N,从第 K (1<=K<=N)个人开始报数,数到 M (1<=M<=N)的人将出圈,然后下一个人继续从 1 开始报数,直至所有人全部出圈,求依次出圈的编号。
- 例如N=6,M=5,K=1,被杀掉的顺序是:5,4,6,2,3,1
大致思路
-
遍历链表找到指定位置的节点
-
用一个front保存指定节点的前一个节点,方便删除
-
当count==time时,删除此时正在遍历的节点,放入数组中,并将count的值初始化
-
用一个变量loopTime记录已经出圈了几个人,当其等于length时则是最后一个节点,直接放入数组并返回数即可
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 | public class Joseph { public static void main(String[] args) { CyclicSingleLinkedList list = new CyclicSingleLinkedList(); list.addBoy( 5 ); list.showBoy(); list.countBoy( 1 , 2 , 5 ); } } class CyclicSingleLinkedList{ private Boy first = null ; public void addBoy( int sum){ if (sum< 1 ){ System.out.println( "加入的数据不正确" ); return ; } Boy temp = null ; for ( int i = 1 ; i <= sum; i++){ Boy boy = new Boy(i); if (i == 1 ){ first = boy; first.setNext(first); //构成环状 temp = first; } else { temp.setNext(boy); boy.setNext(first); temp = boy; } } } /** * * @param startNo 从第几个男孩开始数 * @param countNum 表示数多少个 * @param nums 表示一共有多少个男孩 */ public void countBoy( int startNo, int countNum, int nums){ if (first == null || startNo < 1 || startNo > nums){ System.out.println( "输入的数据不正确,请重新输入" ); return ; } Boy helper = first; while ( true ){ if (helper.getNext() == first){ //说明已经找到了最后一个小孩的节点 break ; } helper = helper.getNext(); } for ( int i = 0 ; i < startNo - 1 ; i++){ first = first.getNext(); //找到第一个报数的男孩 helper = helper.getNext(); //找到第一个报数的男孩的前一个节点 } while ( true ){ if (helper == first){ //说明还剩最后一个节点了 break ; } for ( int j = 0 ; j < countNum - 1 ; j++){ first = first.getNext(); //找到要删除的节点 helper = helper.getNext(); } System.out.printf( "要出列的男孩是%d \n" , first.getNo()); first = first.getNext(); helper.setNext(first); } System.out.println( "最后一个男孩是:" +first.getNo()); } public void showBoy(){ if (first == null ) { System.out.println( "没有小男孩" ); return ; } Boy temp = first; while ( true ){ System.out.printf( "男孩编号为 %d\n" ,temp.getNo()); if (temp.getNext() == first){ break ; } temp = temp.getNext(); } } } class Boy{ private int no; private Boy next; public Boy( int no) { this .no = no; } public int getNo() { return no; } public void setNo( int no) { this .no = no; } public Boy getNext() { return next; } public void setNext(Boy next) { this .next = next; } } |
本文来自博客园,作者:腹白,转载请注明原文链接:https://www.cnblogs.com/wyh518/
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?