• 约瑟夫环问题


    一、问题描述

    1.1 问题

      题目描述:

      • (1)编号为[1,2,…,n]的n个人按顺时针方向围坐一圈(一般给定一个数,从1~n)
      • (2)任选一个正整数作为报数上限m,从第一个人开始按顺时针方向从自1开始顺序报数,
      • (3)报到m时停止报数,报m的人出列
      • (4)从上一个出列得人顺时针方向上的下一个人开始重新从1报数
      • (5)如此下去

    1.2 提问方式

    • (1)输出出队顺序
    • (2)输出最后一个出队的编号

    二、输出出队顺序

      实现思想:利用双端队列模拟整个过程。代码如下:

     1 vector<int> getOrder(int n, int k)
     2 {
     3     deque<int> q;
     4     //开始将所有数字正确入队,1在队头,n在队尾
     5     for (int i = 1; i <= n; i++)
     6         q.push_back(i);
     7 
     8     //保存出队顺序
     9     vector<int> ans;
    10 
    11     //报数记录
    12     int cnt = 0;
    13 
    14     //队列不为空就继续报数
    15     while (!q.empty())
    16     {
    17         cnt++;
    18         //如果当前报数等于k,就将其出队,并保存在结果中
    19         if (cnt == k)
    20         {
    21             ans.push_back(q.front());
    22             q.pop_front();
    23             //重置报数
    24             cnt = 0;
    25         }
    26         else
    27         {
    28             //如果当前报数不等于k,将其插队队尾,等待下一轮的报数
    29             q.push_back(q.front());
    30             q.pop_front();
    31         }
    32     }
    33 
    34     //返回结果
    35     return ans;
    36 }

    三、最后出队的数字

      思路:反向模拟!

      进行公式推算:由于我们需要求最后一个出队人的编号,而最后一个出队人的编号一定为1,所以我们需要反推,也就是说通过新编号推算得到旧编号!

      • 旧编号 --> 新编号:(旧编号 - 报数值)% 旧人数
      • 新编号 --> 旧编号:(新编号 + k)% 旧人数,也就是old_index = (new_index + k) % old_number

      最后,我们经过n-1次的公式计算即可反推得到最后一个出队人的本来的序号

      需要注意的是,上述推导的公式必须从0开始才有效也就是说我们将上述图中所有的值都减去1,最后输出时再加上1即可。

      代码如下:

     1 int getLastNum(int n, int k)
     2 {
     3     //新编号,且最后一个人的编号,无论如何都是0。
     4     int index = 0;
     5 
     6     //i代表上一轮剩余的人数
     7     for (int i = 2; i <= n; i++)
     8     {
     9         index = (index + k) % i;
    10     }
    11 
    12     //返回编号
    13     return index + 1;
    14 }

    四、参考文章

    http://182.92.190.128/archives/suan-fa-12--yue-se-fu-huan-wen-ti

    本文来自博客园,作者:Mr-xxx,转载请注明原文链接:https://www.cnblogs.com/MrLiuZF/p/15243182.html

  • 相关阅读:
    常见前端面试题CSS部分
    window.location
    实时时间设置
    常用兼容处理
    背景淡入淡出切换
    常用插件
    PHP文件处理函数
    PHP的数据处理函数二(数组)
    php的数据处理函数一(字符串)
    PHP环境搭建(phpstudy)
  • 原文地址:https://www.cnblogs.com/MrLiuZF/p/15243182.html
Copyright © 2020-2023  润新知