您的位置:首页 > Web前端

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

2016-06-25 11:33 399 查看
题目: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;
}
 该方案的效率比方案提高很多,推荐!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: