解题笔记(10)——约瑟夫环问题

本文介绍了约瑟夫环问题,通过简化问题描述,提出利用环链表和STL单链表来解决,但指出这种方法效率低下,时间复杂度为O(mn)。进一步通过数学推导,给出了递推公式f[i] = (f[i - 1] + m) % i,用于高效求解。最后,讨论了不同轮次中删除的数字和获胜者的编号计算方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        约瑟夫环问题的原来描述为,设有编号为1,2,……,n的n(n>0)个人围成一个圈,从第1个人开始报数,报到m时停止报数,报m的人出圈,再从他的下一个人起重新报数,报到m时停止报数,报m的出圈,……,如此下去,直到所有人全部出圈为止。当任意给定n和m后,设计算法求n个人出圈的次序。  稍微简化一下。

        问题描述:n个人(编号0~(n-1)),从0开始报数,报到(m-1)的退出,剩下的人继续从0开始报数。求胜利者的编号。 

        思路:容易想到的就是用环链表来做,构建一个环链表,每个结点的编号为0, 1, ...... n-1。每次从当前位置向前移动m-1步,然后删除这个结点。最后剩下的结点就是胜利者。给出两种方法实现,一种是自定义链表操作,另一种用是STL库的单链表。不难发现,用STL库可以提高编写速度。

struct ListNode
{
	int num;        //编号
	ListNode *next; //下一个
	ListNode(int n = 0, ListNode *p = NULL) 
	{ num = n; next = p;}
};

//自定义链表实现
int JosephusProblem_Solution1(int n, int m)
{
	if(n < 1 || m < 1)
		return -1;

	ListNode *pHead = new ListNode(); //头结点
	ListNode *pCurrentNode = pHead;   //当前结点
	ListNode *pLastNode = NULL;       //前一个结点
	unsigned i;

	//构造环链表
	for(i = 1; i < n; i++)
	{
		pCurrentNode->next = new ListNode(i);
		pCurrentNode = pCurrentNode->next;
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值