zoukankan      html  css  js  c++  java
  • 约瑟夫环(Josehpuse)的模拟

    约瑟夫环问题:

    0,1,...,n-1这n个数字排成一个圆圈,从数字0开始每次从这个圆圈里删除第m个数字,求出这个圆圈里剩下的最后一个数字。

    这里给出以下几种解法,

    1.用队列模拟

    每次将前m-1个元素出队,出队元素放入队列的末尾,再循环即可,这种方法时间复杂度为O(mn)(每找出一个数字需要m步运算,要找出n人数字),空间复杂度为O(n),用于存放队列,运行结果如下。

    2.环形链表模

    时间复杂度为O(mn),空间复杂度为O(n)

    代码如下(vs2015调试正常):

     1 //Josephuse环问题
     2 #include <iostream>
     3 #include <cstdlib>
     4 #include <queue>
     5 #include <vector>
     6 #include <list>
     7 
     8 
     9 using namespace std;
    10 
    11 //用队列模拟
    12 void Q_Joes(int n, int m)
    13 {
    14     queue<int> Q;
    15     vector<int> result;
    16     for (int i = 0; i < n; i++) {
    17         Q.push(i);
    18     }
    19     int count = m;
    20     while (!Q.empty()) {
    21         while (--count) {
    22             Q.push(Q.front());
    23             Q.pop();
    24         }
    25         result.push_back(Q.front());
    26         Q.pop();
    27         count = m;
    28     }
    29     for (auto i : result)
    30         cout << i << " ";
    31     cout << endl;
    32     cout << result[result.size() - 1];
    33     cout << endl;
    34 }
    35 
    36 //用循环链表来模拟,当单链表迭代器到末尾时,将其移到链表的开头,以此来模拟一个环形链表
    37 void List_Joes(int n, int m)
    38 {
    39     if (n < 1 || m < 1)
    40         return;
    41     list<int> L;
    42     vector<int> result;
    43     int i;
    44     for (i = 0; i < n; ++i)
    45         L.push_back(i);
    46     list<int>::iterator curNode = L.begin();
    47     while (L.size() > 0) {
    48         //找到第m个数字
    49         for (int i = 1; i < m; ++i) {
    50             curNode++;
    51             if (curNode == L.end())
    52                 curNode = L.begin();
    53         }
    54 
    55         auto next = ++curNode;
    56         if (next == L.end())
    57             next = L.begin();
    58         --curNode;
    59         result.push_back(*curNode);
    60         L.erase(curNode);
    61         curNode = next;
    62 
    63     }
    64     for (auto i : result)
    65         cout << i << " ";
    66     cout << endl;
    67     cout << result[result.size() - 1];
    68     cout << endl;
    69 }
    70 
    71 int main()
    72 {
    73     int n, m;
    74     cin >> n >> m;
    75     Q_Joes(n, m);
    76     List_Joes(n, m);
    77     system("pause");
    78     return 0;
    79 }

    3.数学解法

    当n为1时,最后剩下的数字为0

    当n大于1时,f(n,m) = f'(n -1,m) = (f(n -1,m) + m) %n

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 
     4 int main()
     5 {
     6     int n, m,i,last;
     7     scanf("%d%d", &n, &m);
     8     last = 0;
     9     for (i = 2; i <= n; i++)
    10         last = (last + m) % i;
    11     printf("%d
    ", last);
    12     system("pause");
    13     return 0;
    14 }

     

     

    只为训练自己,时刻锤炼一个程序员最基本的技能!
  • 相关阅读:
    C#防止窗口重复打开
    c#image与byte数组的转换
    物理网卡地址
    C#[WinForm]实现自动更新
    js计算散点图方程式
    js遮罩效果
    js实现四舍六入 奇进偶舍
    ajax加载表格数据
    C#创建和调用WebService详细教程
    .NET中的CTS、CLS和CLR
  • 原文地址:https://www.cnblogs.com/coding-wtf/p/5785310.html
Copyright © 2011-2022 走看看