开发者学堂课程【Go 语言核心编程 - 数据结构和算法: 数据结构和算法-约瑟夫问题解决(2)】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/627/detail/9847
数据结构和算法-约瑟夫问题解决(2)
现在已经有了一个小孩了,现在就要解决一个核心问题,就是算法。算法其实是有固定算法的,比如识别算法或者是编码算法,但是也有些针对实际问题解决的,就是自己设计的一些解决方案,都可以叫做算法。
现在至少我们要知道接收的几个变量,就是链表是什么,k数到几,k和m很重要,至于用几个小孩n不是很重要,因为把头结点给到之后就自然知道是几个了。
/*
设编号为1.2。n的n个人围坐一圈,约定编号为k(1<=k<=n)
的人从1开始报数,数到m的那个人出列,它的下一位又从1开始报数,数到m的那个人又出列,依次类推,直到所有人出列为止,由此产生一个出队编号的序列
*/
//分析思路
//1.编写一个函数,PlayGame(first*Boy,startNo int,countNum int)
//2.最后我们使用一个算法,按照要求,在环形链表中留下最后一个人
Func Playgame(first*Boy,startNo int,countNum int)虽然只有一个小孩 但是数多少下都可以
//1、空的链表我们单独的处理
if first. Next == nil(
fmt. Println("空的链表,没有小孩")
Return
//留一个,判断 startNo<=小孩总数
//2.需要定义辅助指针,帮助我们删除小孩
tall:=first
//3.让 tail 执行环形链表的最后一个小孩,这个非常的重要
//因为 tail 在删除小孩时需要使用到
For {
If Tail.Next==first{ //说明 tail 到了最后的小孩
break
}
Tail = tail.Next
}
//4.让 first 移动到 startNo(这个时候就不需要辅助结点,因为最后它也会被删掉)[后面我们删除小孩就以 first 为准,first 指向谁就删掉谁]
For i:=1;ii<==startNo - 1;i++{
First = first.Next
Tail = tail.Next
}
//5.开始数 countnum,然后就删除 first 指向的小孩
For {
//开始数countNum-1次
For i :=1;i<=countNum-1;i++{
}
Fmt.printf(“小孩的编号为%d 出圈->”,first.No)
//删除first执行的小孩
first.Next=first
tail.Next=first
//判断如果 tail ==first,圈子中只有一个小孩
If tail==first{
break
}
}
Fmt.printf(“最后出圈的小孩的编号为%d 出圈->”,first.No)
}
只剩一个小孩,它的 first 和 tail 就相等了
因为最后只留一个人,所以这就是循环
这个 for 循环走完环形链表应该是这样的:
此时这两个指针要同时移动,移动到指定的 startNo 要移动 startNo-1 次,比如说从2号开始就移动一次就可以
func main(){
first:=Add Boy(5)
//显示
ShowBoy(first)
PlayGame(first,2,3)
}
输出结果
环形在删除人时候有一个特别重要的就是要有辅助结点
示意图:
现在已经有了一个头结点指向1号,现在还需要一个指针指向5号结点,还需要tali指针指向1号最后,因为如果要删除1号结点没有后边的指针就删除不了,因此现在就需要 tail 指针指向最后。目前 tail 是指向1号的,要是从第二个开始数那么头结点就需要指向2号,然后tail同步向前移动。
再向前移动两步,2号和4号连接,整个链表中3号就出列了,2号与3号之间的线就断掉了,因此三号就变成了一个出列的小孩。