zoukankan      html  css  js  c++  java
  • 剑指Offer解题报告(Java版)——约瑟夫环 45

       

    引言

       

    常见的约瑟夫环问题有用循环链表做的,有用数组做的,这里提供一个用数学公式做的,由此可见,很多计算机的问题如果最终用到数学的知识,时间复杂度会大大的降低

       

    分析问题

       

    首先我们对0n-1删除第一个数进行分析,第一个被删除的数一定是序号为m-1的数,因为0号数了1,1号数了2,m-1号数了m,那么应该删掉m-1号,设m-1号是第k号,这里这样做是因为后面可以扩展,想扩展为m-1%n=k

       

    剩下的数按照序列重排序如下

       

    因为删掉的是k,那么下面第一个就是k+1了,这个很好理解

       

    假设我们设f函数的输出是原来的在n个数中,每次数m下,最后留下的数

       

    而现在删掉了k,只有n-1个数了,每次数m下,最后留下的数是f'(n-1,m)

       

       

    如何建立ff'之间的关系呢

       

    我们对重排序之后的数做一个映射

       

       

    该映射为

    p(x) -- > y ::: y=(x-k-1)%n

       

    则映射完之后就跟原来的问题一样了,也就是f(n-1,m)了

       

    也就是p(f'(n-1,m)=f(n-1,m)

       

    而我们现在只有f(n,m)和f'(n-1,m)之间的关系

       

    所以我们还需要再转换一下,也就求映射的逆

       

       

    而映射p的逆映射为

       

    o(y) -- >x x=(y+k+1)%n

       

    其中k可以替换 k%n=(m-1)%n

       

    o(y) -- >x x=(y+m)%n

       

    对应到之前f(n-1,m)f'(n-1,m)之间的关系

       

    f'(n-1,m)=f(n-1,m)+m%n

       

       

    f(n,m)=f'(n-1,m)

       

    这样我们有f(n,m)f'(n-1,m)之间的关系,也有f(n-1,m)f'(n-1,m)之间的关系

       

    带入之前的式子推到得到

       

       

    解决问题

       

    static int lastRemain(int n, int m) {

    int last = 0;

    if (n < 1 || m < 1) {

    return -1;

    }

    for (int i = 2; i <= n; i++)

    last = (last + m) % i;

    return last;

    }

       

  • 相关阅读:
    编程基础——c 选择结构程序设计个人总结实例
    编程基础C——常量,变量,运算符个人总结
    编程基础C——格式化输入函数scanf的应用
    编程基础C——基本数据类型个人总结:
    django-base
    django-mvc
    OSI七层与TCP/IP五层网络架构详解
    tcp/ip三次握手及四次挥手
    网页浏览过程
    http协议
  • 原文地址:https://www.cnblogs.com/keedor/p/4474536.html
Copyright © 2011-2022 走看看