初始化单向环形链表![请添加图片描述](https://i-blog.csdnimg.cn/blog_migrate/9a179843b7cecb9eb5988674136e087a.png)
丢手绢示意图
![请添加图片描述](https://i-blog.csdnimg.cn/blog_migrate/65101652dc2cb767f6ed4288ff7a63f6.png)
实现代码
package linkedlist.josephu
import scala.util.control.Breaks._
object Josephu {
def main(args: Array[String]): Unit = {
val boyGame = new BoyGame
boyGame.addBoy(7)
// boyGame.showBoy()
boyGame.playGame(4, 3, 7)
}
}
class Boy(num: Int) {
val no: Int = num
var next: Boy = null
}
class BoyGame {
// 定义一个初始的头节点
private var firstBoy = new Boy(-1)
// 初始化形成单向环形节点
def addBoy(nums: Int): Unit = {
if (nums < 1) {
println("nums的值不正确")
return
}
var curBoy: Boy = null // 辅助指针
for (num <- 1 to nums) {
val boy = new Boy(num)
if (num == 1) {
firstBoy = boy
boy.next = firstBoy //形成一个环形链表
curBoy = firstBoy
} else {
curBoy.next = boy
boy.next = firstBoy //形成一个环形链表
curBoy = boy
}
}
}
def showBoy(): Unit = {
if (firstBoy.next == null) {
println("没有任何小孩")
}
var curBoy = firstBoy
breakable {
while (true) {
printf("小孩编号:%d\n", curBoy.no)
if (curBoy.next == firstBoy) {
break
}
curBoy = curBoy.next
}
}
}
/**
*
* @param startNum 开始数的位置
* @param countNum 数的次数
* @param totalNum 总的有多少人
*/
def playGame(startNum: Int, countNum: Int, totalNum: Int): Unit = {
// 参数合理性校验
if (startNum < 1 || startNum > totalNum || countNum < 1 || firstBoy.next == null) {
print("参数不对,无法完成")
return
}
// 1、找到链表的first前面一个指针
var helper = firstBoy
breakable {
while (true) {
if (helper.next == firstBoy) {
break()
}
helper = helper.next
}
}
// 2、从第几个小朋友还是数i
for (i <- 0 until startNum - 1) {
firstBoy = firstBoy.next
helper = helper.next
}
// 3、开始一直数,直到只剩下一个小朋友在圈里
breakable {
while (true) {
// 如果只剩下最后一个的时候下面条件满足
if (helper == firstBoy) {
break()
}
// 一个一个围着数,firstBoy就是本次出圈的小朋友
for (i <- 0 until countNum - 1) {
firstBoy = firstBoy.next
helper = helper.next
}
printf("小朋友%d 出圈\n", firstBoy.no)
// 踢出圈,只需要把当前小朋友的指针指向下一位,并把后面的指针跟着移动
firstBoy = firstBoy.next
helper.next = firstBoy
}
}
printf("小朋友%d是最后一位出圈\n", firstBoy.no)
}
}