zoukankan      html  css  js  c++  java
  • 剑指Offer——孩子们的游戏(圆圈中最后剩下的数)

    题目描述:

    每年六一儿童节,牛客都会准备一些小礼物去看望孤儿院的小朋友,今年亦是如此。HF作为牛客的资深元老,自然也准备了一些小游戏。其中,有个游戏是这样的:首先,让小朋友们围成一个大圈。然后,他随机指定一个数m,让编号为0的小朋友开始报数。每次喊到m-1的那个小朋友要出列唱首歌,然后可以在礼品箱中任意的挑选礼物,并且不再回到圈中,从他的下一个小朋友开始,继续0...m-1报数....这样下去....直到剩下最后一个小朋友,可以不用表演,并且拿到牛客名贵的“名侦探柯南”典藏版(名额有限哦!!^_^)。请你试着想下,哪个小朋友会得到这份礼品呢?(注:小朋友的编号是从0到n-1)


    分析:

     这是约瑟夫环(约瑟夫问题)。

    问题是从n个人编号分别为0...n-1,取第m个,
    则第m个人编号为m-1的淘汰,剩下的编号为0,1,2,3...m-2,m,m+1,m+2,...
    此时因为从刚刚淘汰那个人的下一个开始数起,因此重新编号
    把m号设置为0,则
    m 0
    m+1 1
    ...
    0 n-m
    1 n-m+1

    假设已经求得了n-1个人情况下的最终胜利者保存在f[n-1]中,
    则毫无疑问,该胜利者还原到原来的真正编号即为 (f[n-1]+m)%n。
    (因为第二轮重新编号的时候,相当于把每个人的编号都减了m,因此重新+m即可恢复到原来编号)。
    由此,我们可以想象,当最终只剩下一个人的时候,该人即为胜利者,此时重新编号,因为只有一个人,
    所以此时f[1]=0。
    这样f[2]=(f[1]+m)%2,这样就可以求出最终胜利者在2个人的时候的情况下的编号,
    由递推公式f[n]=(f[n-1]+m)%n,可递推到最初编号序列中该胜利者的编号。


    代码:

    1 class Solution {
    2 public:
    3     int LastRemaining_Solution(int n, int m) {
    4         if(n == 0 || m == 0) return -1;
    5         int res = 0;
    6         for(int i = 2; i <= n; i++) res = (res + m) % i;
    7         return res;
    8     }
    9 };
  • 相关阅读:
    什么样的代码称得上是好代码?
    九年程序人生 总结分享
    Docker入门 第一课 --.Net Core 使用Docker全程记录
    阿里云 Windows Server 2012 r2 部署asp.net mvc网站 平坑之旅
    Visual studio 2015 Community 安装过程中遇到问题的终极解决
    Activiti6.0 spring5 工作流引擎 java SSM流程审批 项目框架
    java 进销存 库存管理 销售报表 商户管理 springmvc SSM crm 项目
    Leetcode名企之路
    24. 两两交换链表中的节点
    21. 合并两个有序链表
  • 原文地址:https://www.cnblogs.com/jacen789/p/7747749.html
Copyright © 2011-2022 走看看