剑指offer面试题45圆圈中最后一个数字,约瑟夫环模拟和数学解法

/*
这题也是以前做ACM做的 模拟 还有一种是找数学规律 就是通过函数对应的。
这题其实也没什么好写的 但是里面用了stl的list 我从来没用过。。
*/
#include<iostream>
#include<cstdio>
#include<list>
using namespace std;

int LastRemaining(int n,int m)
{
    if(n<1 || m<1) return -1;
    int i=0;
    list<int> num;
    for(;i<n;++i)
    num.push_back(i);
    list<int>::iterator cur=num.begin();
    while(num.size()>1)
    {
        for(int i=1;i<m;++i)
        {
            cur++;
            if(cur==num.end())
            cur=num.begin();
        }
        list<int>::iterator next=++cur;//next指向最后一个的下一个
        if(next==num.end())
            next=num.begin();
        cur--;
        num.erase(cur);
        cur=next;
    }
    return * cur;
}
/*
这种方法就是通过数学分析 分析过程挺复杂的 但是代码很简单
思路大概是用f(n,m)表示 从0到n-1 每次删第m个 最后剩下的数字
那么第一次删除的是(m-1)%n
第二次 这个序列就不是原来那种的规则了
我们用一种映射变称规则的 就是P(x)=(x-k-1)%m;
这个映射的逆映射是 p^(x)=(x+k+1)%m;
这样再推导得到 f(n,m)=(f(n-1,m)+m)%n;
*/
int LastRemaining_2(int n,int m)
{
    if(n<1 || m<1) return -1;
    int ans=0;
    for(int i=2;i<=n;++i)
    ans=(ans+m)%i;
    return ans;
}
int main()
{
    int n,m;
    cin>>n>>m;
    int ans=LastRemaining_2(n,m);
    cout<<ans<<endl;
    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值