zoukankan      html  css  js  c++  java
  • 《剑指offer》第六十二题:圆圈中最后剩下的数字

    // 面试题62:圆圈中最后剩下的数字
    // 题目:0, 1, …, n-1这n个数字排成一个圆圈,从数字0开始每次从这个圆圈里
    // 删除第m个数字。求出这个圆圈里剩下的最后一个数字。
    
    #include <cstdio>
    #include <list>
    
    using namespace std;
    
    // ====================方法1====================
    int LastRemaining_Solution1(unsigned int n, unsigned int m)
    {
        if (n < 1 || m < 1)
            return -1;
    
        list<int> numbers;
        for (unsigned int i = 0; i < n; ++i) //构造链表
            numbers.push_back(i);
    
        list<int>::iterator current = numbers.begin();
        while (numbers.size() > 1) //剩余最后一个数字跳出
        {
            for (int i = 1; i < m; ++i) //跳到第m个数字. 从本位计算第一个数字, 因此是m-1
            {
                ++current;
                if (current == numbers.end()) //环式链表
                    current = numbers.begin();
            }
    
            list<int>::iterator next = ++current; //删除后指向的数字 k+1
            if (next == numbers.end()) //环式链表
                next = numbers.begin();
    
            --current;
            numbers.erase(current); //删除第m个数字
            current = next;
        }
        return *current;
    }
    
    // ====================方法2====================
    // 数学推导牛逼
    int LastRemaining_Solution2(unsigned int n, unsigned int m)
    {
        if (n < 1 || m < 1)
            return -1;
    
        int last = 0;
        for (int i = 2; i <= n; ++i)
            last = (last + m) % i;
    
        return last;
    }
    // ====================测试代码====================
    void Test(const char* testName, unsigned int n, unsigned int m, int expected)
    {
        if (testName != nullptr)
            printf("%s begins: 
    ", testName);
    
        if (LastRemaining_Solution1(n, m) == expected)
            printf("Solution1 passed.
    ");
        else
            printf("Solution1 failed.
    ");
    
        if (LastRemaining_Solution2(n, m) == expected)
            printf("Solution2 passed.
    ");
        else
            printf("Solution2 failed.
    ");
    
        printf("
    ");
    }
    
    void Test1()
    {
        Test("Test1", 5, 3, 3);
    }
    
    void Test2()
    {
        Test("Test2", 5, 2, 2);
    }
    
    void Test3()
    {
        Test("Test3", 6, 7, 4);
    }
    
    void Test4()
    {
        Test("Test4", 6, 6, 3);
    }
    
    void Test5()
    {
        Test("Test5", 0, 0, -1);
    }
    
    void Test6()
    {
        Test("Test6", 4000, 997, 1027);
    }
    
    int main(int argc, char* argv[])
    {
        Test1();
        Test2();
        Test3();
        Test4();
        Test5();
        Test6();
    
        return 0;
    }
    测试代码

    分析:推导过程很好。效率提升近8倍。

    class Solution {
    public:
        int LastRemaining_Solution(int n, int m)
        {
            if (n < 1 || m < 1)
                return -1;
            
            list<int> numbers;
            for (unsigned int i = 0; i < n; ++i)
                numbers.push_back(i);
            
            list<int>::iterator current = numbers.begin();
            while (numbers.size() > 1)
            {
                for (int i = 1; i < m; ++i)
                {
                    ++current;
                    if (current == numbers.end())
                        current = numbers.begin();
                }
                
                list<int>::iterator next = ++current;
                if (next == numbers.end())
                    next = numbers.begin();
                
                --current;
                numbers.erase(current);
                current = next;
    
            }
            return *current;
        }
    };
    牛客网-方法一
    class Solution {
    public:
        int LastRemaining_Solution(int n, int m)
        {
            if (n < 1 || m < 1)
                return -1;
            
            int last = 0;
            for (int i = 2; i <= n; ++i)
                last = (last + m) % i;
            
            return last;
        }
    };
    牛客网-方法二
  • 相关阅读:
    git线上操作
    IDEA快捷方式
    Java 四种线程池
    java 获取当前天之后或之前7天日期
    如何理解AWS 网络,如何创建一个多层安全网络架构
    申请 Let's Encrypt 通配符 HTTPS 证书
    GCE 部署 ELK 7.1可视化分析 nginx
    使用 bash 脚本把 AWS EC2 数据备份到 S3
    使用 bash 脚本把 GCE 的数据备份到 GCS
    nginx 配置 https 并强制跳转(lnmp一键安装包)
  • 原文地址:https://www.cnblogs.com/ZSY-blog/p/12688070.html
Copyright © 2011-2022 走看看