美文网首页
剑指offer 70- 圆圈中最后剩下的数字

剑指offer 70- 圆圈中最后剩下的数字

作者: 顾子豪 | 来源:发表于2021-06-09 00:03 被阅读0次

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

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

    输入:n=5 , m=3
    
    输出:3
    

    分析:
    算法一:约瑟夫环问题
    直接暴力
    时间复杂度O(m*n)

    class Solution {
    public:
        int lastRemaining(int n, int m){
            vector<int> nums;
            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();
        }
    };
    

    算法二:
    时间复杂度:O(N)

    首先寻找递推公式
    首先定义最初的n个数字(0,1,…,n-1)中最后剩下的数字是关于n和m的方程为f(n,m)
    0,1,2,...,m-1,m,...,n-1
    m个数删掉,即m-1删掉,然后剩下
    0,1,2,...,m,m+1,...,n-2
    对这些数重新编号
    m --->> 0
    m+1 --->> 1
    m+2 --->> 2
    m+3 --->> 3
    ...
    寻找映射关系:(新+m)%n
    f(n,m) =(f(n-1,m) + 1)%n

    递归写法:

    class Solution {
    public:
        int lastRemaining(int n, int m){
            if(n==1) return 0;
            return (lastRemaining(n-1,m)+m)%n;
        }
    };
    

    递推写法:

    class Solution {
    public:
        int lastRemaining(int n, int m){
            // if(n==1) return 0;
            // return (lastRemaining(n-1,m)+m)%n;
            
            if (n == 1) return 0;
            vector<int> f(n + 1);
            f[1] = 0;
            for(int i = 2; i <= n; i ++){
                f[i] = (f[i - 1] + m) % i; //核心递推关系式
            }
            return f[n];
            
        }
    };
    

    相关文章

      网友评论

          本文标题:剑指offer 70- 圆圈中最后剩下的数字

          本文链接:https://www.haomeiwen.com/subject/qjcxsltx.html