【约瑟夫问题】【队列】平凡的约瑟夫(Ordinary Josephus)

描述

n个人围成一圈,编号分别为从1到n.从第1个人开始报数,数到2的人出列,再由下一个人重新从1开始报数,数到2的人再出列,……依次类推,直到只剩下一个人.请输最后一个人的编号.

(n<=100000)

输入

一个整数n

输出

若有解,则输出最后一个人的编码f(n)

若无解,则输出"No Solution."

输入样例 1 

3

输出样例 1

3

这道题看起来很简单,但是n的大小让人汗颜,可能用循环链表都会超时。

那用队列怎么样?

用队列做约瑟夫问题是我上厕所的时候想到的(不要问我为什么qwq),先上代码:

#include<iostream>
#include<queue>
using namespace std;
int main()
{
	queue<long long> p;
	long long n,i,js;
	cin>>n;
	if(n<=0)cout<<"No Solution.";
	else
	{
		for(i=1;i<=n;i++)p.push(i);
		for(js=0;js!=n-1;js++)
		{
			p.push(p.front());
			p.pop();
			p.pop();
		}
		cout<<p.back();
	}
	return 0;
}

比循环链表还要短,而且效率非常高!(虽然递推式出来两个都得趴下)

思路:先将一到n填入队列,然后把队头加到队尾(还在圈内),删除队头,再删除一次队头(表示下一个出圈),这样循环n-1次,最后留下的就是答案。

效率高是因为它没有使用除for以外的任何判断,这是链表也不具有的速度。唯一的缺点就是:它很烧空间qwq,n再大一点会炸掉(我也没办法)

关于约瑟夫问题如果有更高效的做法,欢迎留言!

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值