【剑指offer】约瑟夫环问题

【剑指offer】约瑟夫环问题_第1张图片
推公式一:
理解原始的约瑟夫环问题,简化为10个人,报数到3枪毙。【剑指offer】约瑟夫环问题_第2张图片
那么我们此时用f(n)表示n个人的时候,能够存活的位置索引。由上图显然可以得到f(1)=0,f(2)=1,…,f(10)=3。但是我们要找的是通项公式。从图中也可以很直观的看到,n=9时d的位置索引就是n=10时循环左移了3位。那么可以得到f(10) = (f9 + 3) % 10,因为是循环左移,所以需要加一个取余,防止越界。同理可以得到f(3) = (f(2)+3)%3,f(2) = (f(1) + 3) % 2。
从始至终,m只是一个常量。所以不影响结论。所以约瑟夫环问题的公式:

f(n,m) = (f(n-1, m) + m) mod n

推公式二:

把n个人的编号改为0~n-1,然后对删除的过程进行分析。
第一个删除的数字是(m-1)%n,记为k,则剩余的编号为(0,1,…,k-1,k+1,…,n-1),下次开始删除时,顺序为(k+1,…,n-1,0,1,…k-1)。
用f(n,m)表示从(0~n-1)开始删除后的最终结果。
用q(n-1,m)表示从(k+1,…,n-1,0,1,…k-1)开始删除后的最终结果。
f(n,m)=q(n-1,m)。

下面把(k+1,…,n-1,0,1,…k-1)转换为(0~n-2)的形式,即
k+1对应0
k+2对于1

k-1对应n-2
转化函数设为p(x)=(x-k-1)%n, p(x)的逆函数为p^(x)=(x+k+1)%n
则f(n,m)=q(n-1,m)=p^(f(n-1,m))=(f(n-1,m)+k+1)%n,又因为k=(m-1)%n。
f(n,m)=(f(n-1,m)+m)%n;

最终的递推关系式为
f(1,m) = 0; (n=1)
f(n,m)=(f(n-1,m)+m)%n; (n>1)

    public int LastRemaining_Solution(int n, int m) {
        if(n<=0)
            return -1;
        if(n==1)
            return 0;
        return (LastRemaining_Solution((n-1),m)+m)%n;
    }

你可能感兴趣的:(剑指offer,dfs)