先来聊聊什么是约瑟夫环,有编号为1,2,3...n个小朋友围成一圈坐,让编号为k[1,n]的下朋友开始从1报数,数到m的那个小朋友出圈,下一个小朋友接着从1开始报数,数到m的小朋友继续出圈,循环执行此操作,直至圈中所有小朋友都出圈,由此得到的出圈编号。
这里我用单向环形链表来实现约瑟夫环,在添加每个节点时,让新加入的节点的next域指向第一个节点first。下图是一个单向环形链表。
由于单链表不能实现自我删除,所以我们需要一个helper指针指向待删除节点的前一个节点。假设从第一个节点开始,first指向这个节点,helper则指向最后一个节点(若从第k个节点开始,first和helper移动k-1次);开始数时,first和helper移动m-1次,移动后的first指向要出圈的节点,此时让first = first.next, helper.next = first,即可完成一次出圈;循环执行加粗部分,直至first == helper,此时圈中只剩下一个节点,将其出圈即可。下面是一个简单的圈图和代码实现。
Node.java