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 };
  • 相关阅读:
    ncover
    bash
    .net framework 工具
    keePass
    jersey
    i-jetty
    如何查看set环境变量的更改
    C语言丨如果你不是程序员,绝对看不懂这三个符号!(= 和==、!=)
    忘记 root 密码怎么办?教你4种使用MySQL方式修改密码!(超实用)
    一线城市容不下肉体,二三线城市安放不了灵魂,程序员何处为家?
  • 原文地址:https://www.cnblogs.com/jacen789/p/7747749.html
Copyright © 2011-2022 走看看