牛客网. 环形链表的约瑟夫问题

题目概述

解题思路

如果采用环形链表实现,这题的时间和空间复杂度均为O(n),比较麻烦。

这里采用一个取巧的方法,通过递推公式推出最后一个被删除的元素的序号。

这道题的一个复杂之处在于,每次删除了当前数环中的一个元素以后,剩下元素的序号和它的值是不对应的。要想知道最后留下了哪个元素,就需要根据它在数环的相对序号来倒推原始的位置。

我们已知删至只剩一个元素时,该元素的序号为1;假设当数环长度为i时,待删元素的序号为Num(i),Num(1) = 1。我们现在需要明确的就是Num(i)和Num(i-1)的关系。

首先考虑一下,当数环中有i个元素时,报数A的节点编号为B,A与B的关系:B = (A - 1)%i + 1

接下来考虑从长为i的环变为长为i - 1的环时,环中元素的编号变化。假设长为i的环中,被删除元素的编号为d,其余元素在删除元素之前的编号为old,在删除元素以后的编号为new,则new 与 old的关系是:old = (new + s - 1) % i + 1

由于每次删除的元素报数为m,即A = m, 故B = (m - 1)%i+1,也即 s = (m-1)%i+1;带入后一个等式可知, old = (new + (m-1)%i + 1 - 1)%i+1 = (new + m - 1) % i + 1

考虑最后剩下的那个节点,它的序号递推公式为:Num(i) = (Num(i - 1) + m - 1) % i + 1,Num(1) = 1。考虑将该公式递推N次,可得原始数组中该元素的序号。

算法性能

代码样例

class Solution {
public:
    /**
     * 
     * @param n int整型 
     * @param m int整型 
     * @return int整型
     */
    int ysf(int n, int m) {
        // write code here
        int PC = 1;
        for (int i = 1; i <= n; ++i)
		    PC = (PC + m - 1) % i + 1;
        return PC;
    }
};

一些思考

考虑这道题的一个变种:如何按序输出被删除的第k个元素(k = 1,...n)?

其实第k个元素的特性是:Num(N - k) = 0。我们只需将这个其实式带入递推公式求解即可。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值