【算法百题之四】约瑟夫环变形问题

     【算法百题之四】约瑟夫环变形问题

 

       大家好,我是Lampard~~

       很高兴又能和大家见面了,接下来继续更新的是算法题,一日一练,早日升仙!

 

       今天的问题是:

       现在有50个人围圈圈,选其中一个人开始报数出列,然后每隔一人循环报数出列直至剩下最后一人为止。问题是:现在我想最后一个人是42号选手,那么请问我该从第几号开始数起呢?

     (默认初始的人按顺序存放在一维数组中)

 

       我的思路:

  从一开始看到这个问题的时候,内心bb:

 42最后?那我大胆猜测它是从41开始数起的!!!

 手写了一遍后,不对。

 那肯定是从43开始的!!!

 再写了一遍后,还是不对。

 

啊!我的脑子快疼死了,怎么还不对!!(等等,我根本没有脑子)

既然手写算不出来,为何不用编程实现呢?我不单只要写出42最后是谁开始数,我还要随便输入一个最后输出的数,要程序就返回给我开始数的位置!!!于是,代码,它来啦!!!

#include "pch.h"
#include <iostream>
#include <queue>
#include <string>

using namespace std;

int Key;

 int GetNum(int* array) 
{
	 int num = 2;
	 // num是报数的数字,当num==2时出列

	 queue <int> A;
	 queue <int> B;

	 // 第一步把一维数组里面的名字转进去队列A处
	 for (int i = 0; i < 50; i++)
	 {
		 if (num == 2)
		 {
			 num = 1;
		 }

		 else
		 {
			 num++;
			 A.push(array[i]);
		 }
	 }

	 int flag = 1;
	 // flag是判断队列AB是否都为空,flag==1时,A非空,flag == 2时,B非空,flag == 0时,AB

	 while (flag != 0)
	 {
		 if (flag == 1)
		 {
			 // 从队列A转队列B
			 while (A.size() != 0)
			 {
				 if (num == 2)
				 {
					 num = 1;
					 A.pop();
				 }

				 else
				 {
					 num++;
					 B.push(A.front());
					 A.pop();
				 }
			 }

			 // 判断B是否为空
			 if (B.size() != 1)
				 flag = 2;
			 else
				 flag = 0;
		 }

		 else if (flag == 2)
		 {
			 while (B.size() != 0)
			 {
				 if (num == 2)
				 {

					 num = 1;
					 B.pop();
				 }

				 else
				 {
					 num++;
					 A.push(B.front());
					 B.pop();
				 }
			 }

			 // 判断A是否为空
			 if (A.size() != 1)
				 flag = 1;
			 else
				 flag = 0;

		 }
	 }

	 if (A.size() != 0)
		 return A.front();

	 else if (B.size() != 0)
		 return B.front();

	 else if (A.size() == 0 && B.size() == 0)
		 return 0;
}

int main()
{
	    int result[50];

		for (int i = 0; i < 50; i++)
		{ // 用了双重循环,待优化
			int array[50];

			for (int k = 0; k < 50; k++)
			{
				array[k] = ((i+k) % 50)+1; // 记得求余哦
			}

			result[i]=GetNum(array);
		}
		
		cout << "请输入想要最后输出的数:" << endl;
		cin >> Key;
		for (int j = 0; j < 50; j++)
		{
			if (result[j] == Key)
			{
				cout << "从第:" << j + 1<< "位开始数起。" <<endl;
				break;
			}

		}
		   
}

 

 上面有我的注释,简单来说就是依据我昨天写的约瑟夫环代码封装成一个函数GetNum()

 然后把每三个人出列,改成每两个人出列。

比较麻烦的是之前我封装的函数是默认从第array【0】位开始出列

那么如果我们想要实现不同位置开始出列,就只能把数组存储内容的顺序进行改变

(例如如果想第一个出列的是第6号兄弟,那么array【0】=6;以此类推)

然后用一个一维数组按顺序存储结果。

最后只需要遍历这个结果数组,你就知道找到你想输出的答案,人那么你就可以把它的索引输出来啦!

 

测试结果:

 

 OK,今天的博客就到这里,谢谢大家!!!

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Lampard杰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值