《剑指offer》:[45]圆圈中最后剩下的数字(约瑟夫(Josephuse)环问题)

题目:0,1,2,3....N-1这N个数排成一个圆圈,从0开始每次从这个圆圈里删除第M个数字。求出这个圆圈里最后一个剩下的数字。
例如0,1,2,3,4这五个数组成一个圆圈,从0开始每次删除第三个数,最后剩下的就是3.

方案一:链表模拟环。这里我们将采用链表的数据结构来描述和解决问题。很明显其时间复杂度为O(M*N),空间复杂度为O(N),(M为删除的第几个元素);

具体分析过程如下;


方案二:找规律,创新法。时间复杂度为O(N),空间复杂度为O(1)。每次删除后,从删除的位置起,开始编号为0,1,2,3...n等,一次循环;
方案一具体实现代码:
#include <iostream>
#include <list>
using namespace std;
bool IsInvalid=false;
int lastRemain( int n, int m)
{
	if(m <1 || n< 1)
	{
		IsInvalid=true;
		return 0;
	}
	list<int> list1;
	for(int i=0;i<n;i++)
		list1.push_back(i);
	list<int>::iterator li=list1.begin();
	while(list1.size()>1)
	{
		for(int i=1;i<m;i++)
		{
			li++;
			if(li==list1.end())
				li=list1.begin();//把头和尾接上;
		}
		list<int>::iterator li2=++li;
		if(li2==list1.end())
			li2=list1.begin();//环不能断;
		li--;
		list1.erase(li);
		li=li2;
	}
	return *li;
}
int main()
{
	int result=lastRemain(5,3);
	if(IsInvalid)
		cout<<"THE INPUT IS INVAID"<<endl;
	else
		cout<<"The last remain number is: "<<result<<endl;
	system("pause");
	return 0;
}

运行结果:


方案二实现代码:
#include <iostream>
using namespace std;
bool IsInvalid=false;
int LastRemain(int n,int m)
{
	if(n<1 || m<1)
	{
		IsInvalid=true;
		return 0;
	}
	int last=0;
	for(int i=2;i<=n;i++)
		last=(last+m)%i;
	return last;
}


int main()
{
	int result=LastRemain(5,3);
	if(IsInvalid)
		cout<<"THE INPUT IS INVAID"<<endl;
	else
		cout<<"The last remain number is: "<<result<<endl;
	system("pause");
	return 0;
}
 该方案的效率比方案提高很多,推荐!
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值