约瑟夫环问题

原题连接

题目描述

0, 1, …, n-1这n个数字(n>0)排成一个圆圈,从数字0开始每次从这个圆圈里删除第m个数字。

求出这个圆圈里剩下的最后一个数字。

输入样例:

n=5 , m=3

输出样例:

3

解题报告

题意理解

这道题首先是从 0 - n 的数字组成一个环,每次从中拿出一个数字,看最后剩下的数字是谁

算法处理

算法一:写一个链表,模拟去除的过程

算法二:

发现数学规律,求递推公式

我们假设 m = 3

并且当 n = 1 时, f(n,m) = 0(幸存者下标)

当 n = 2时,f(2,3) = (f(1,3)+3)%2 = 3%2 = 1

可能有人会问,为什么 n =2 时是这个式子

假设 n , m 时,则被杀的是(m-1)%n,令其等于k

则 n-1,m时,(0,1,…,k-1,k+1,…,n-1)此时从,k+1作第0个,相当于 n 个人时,向右移动 所以 f(n-1,m) = (f(n,m) - m)%(n-1)

那从 n -1到 n,就有 f(n,m) = (f(n-1,m)+m)%n 逆映射

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

代码实现

方法一:

#include <list>
class Solution {
public:
    int lastRemaining(int n, int m){
        
        list<int> nums;
        cin >> n >> m;
        for(int i=0;i<n;i++) nums.push_back(i);
        auto it = nums.begin();
        int k = m -1;
        while(nums.size()>1){
            while(k--){
                it++;
                if(it==nums.end()) it = nums.begin();
            }
            it = nums.erase(it); //删除第m个元素;
            if (it == nums.end()) it = nums.begin();
            k = m - 1;
        }
        return nums.front();
    }
};

方法二:

class Solution {
public:
     int lastRemaining(int n, int m){
         int p = 0; //因为数组是从 0 开始的
         for(int i=2;i<=n;i++){
             p = (p+m)%i;  //递推
         }
         return p;
     }
};
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值