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;
        }
    };
    牛客网-方法二
  • 相关阅读:
    shell 实现word count
    jvm 参数调优
    Java注解处理器(转)
    JVM -XX: 参数介绍(转)
    如何在Linux下重命名多个文件
    Kafka学习之broker配置(0.8.1版)(转)
    linux 历史命令用法(转)
    hive-site.xml 参数设置
    Hadoop-2.2.0 + Hbase-0.96.2 + Hive-0.13.1(转)
    正则表达式通过Unicode属性匹配
  • 原文地址:https://www.cnblogs.com/ZSY-blog/p/12688070.html
Copyright © 2011-2022 走看看