• 约瑟夫环问题分析-C语言经典面试题


      好久没有看有关算法的问题了,今天废了不少劲,再感叹一句:要想学好算法就要常练习,没什么捷径可走。废话不多说,如下:

      问题描述:有m个人,围成一个环,编号为 0、1、2、3、、、m-1,从第一个人开始循环报数,假设数到n的那个人出列,然后从下一个人继续数数,数到n出列,以此循环,最后那个人为胜利者,求胜利者的编号。
      分析如下:
    设m为人的个数 n为要数的数 k为从第几个人开始数
    第一次的数列,记为A
    0 1 2 3 4 5 6 7 8 9 、、、n%m k、、、m-2 m-1
    假设第一次出列了一个人,则编号肯定为n%m-1(减1因为从零开始)。k=n%m,第一次出列后的数列为
    0 1 2 3 4 5 6 7 8 9 、、、k、、、m-2 m-1
    第二次从k开始数数那么可以组成新的数列,记为数列B
    k->0
    k+1->1
    k+2->2
    k+3->3



    k-3->m-3
    k-2->m-2
    如果我们知道了数列B的最终胜利者是的编号是x,那么x在原来数列A中的编号是多少呢?很容易算出来:(x+k)%m,而k=n%m,替换后为(x+n%m)%m=(x+n)%m,(x+n)%m为数列A的胜利者。那么x又该如何求呢,我们可以求数列C,就这样这么以次类推。直到只有一个人时,胜利者的编号肯定为0.
    假设f(y)为胜利者:则有
    f(1)=0;
    f(2)=(f(1)+n)%2;
    f(y)= (f(y-1)+n)%y;(公式) y为数列的人数  n为要数的数

    以下为编程实现,将f(y)替换为number   y替换为i

    /*********************************************************************** 
    **m总人数,则标号为0~m-1   n为要数的数 
    **成功返回序号1~m,失败返回-1 
    ***********************************************************************/  
    int winner(int m, int n)  
    {  
        int i;  
        int number;  
        if (m <= 0 || n <= 0) {  
            return -1;  
        }  
        number = 0;                        /* 当只有一个人时,编号为0的出圈 */  
        for (i = 2;i <= m;i++) {           /* 循环m-1次将剩下一个人         */  
            number = (number + n % i) % i; /* 这样写易理解,或(number+n)%i  */  
        }  
        return number + 1;                 /* 程序从0编号,返回时应+1       */  
    }
  • 相关阅读:
    Selenium2+python自动化55-unittest之装饰器(@classmethod)【转载】
    Selenium2+python自动化54-unittest生成测试报告(HTMLTestRunner)【转载】
    验证码在登录页面的使用
    习课省市区的三级联动(cxselect的使用)
    jira的使用
    springmvc 用拦截器+token防止重复提交
    springMVC发送邮件
    Commons-Collections 集合工具类的使用
    习课的视频播放器 video.js
    习课的redis配置记录
  • 原文地址:https://www.cnblogs.com/mddblog/p/4491443.html
Copyright © 2020-2023  润新知