zoukankan      html  css  js  c++  java
  • 面试题45:圆圈中最后剩下的数字

    题目:0,1,...,n-1这n个数字排成一个圆圈,从数字0开始每次从这个圆圈里删除第m个数字。求出这个圆圈里剩下的最后一个数字。

    例如,0、1、2、3、4这5个数字组成一个圆圈,从数字0开始每次删除第3个数字,则删除的前四个数字一次是2、0、4、1,最后剩下的数字为3.

      本题是有名的约瑟夫环问题。

    解法一:经典的解法,用环形链表模拟圆圈

    如果面试官没有特殊要求,可以用模板库中的list来模拟一个环形链表,而list本身不是一个环形结构,因此每当迭代器扫描到链表末尾的时候,

    要记得把迭代器移到链表的头部。

     1 int lastRemaining(unsigned int n, unsigned int m)
     2 {
     3     if (n < 1 || m < 1)
     4         return -1;
     5     list <int>numbers;
     6     for (int i = 0; i < n; ++i)
     7         numbers.push_back(i);
     8     list<int>::iterator current = numbers.begin();
     9     while (numbers.size() > 1)
    10     {
    11         for (int j = 1; j < m; ++j)
    12         {
    13             ++current;
    14             if (current == numbers.end())
    15                 current = numbers.begin();
    16         }
    17         current = numbers.erase(current);
    18         if (current == numbers.end())
    19             current = numbers.begin();
    20     }
    21     return *current;
    22 }

    这种思路的时间复杂度为O(MN),空间复杂度为O(N)。

    解法二:创新的解法

      首先定义一个关于n和m的方程f(n,m),表示每次在n个数字0,1,...,n-1中每次删除第m个数字后最后剩下的数字。经过分析(过程参考《剑指Offer》)得到:

    n = 1时,f(n,m) = 0;

    n > 1时,f(n,m) = [f(n-1,m)+m]%n;

    1 int lastRemaining(unsigned int n, unsigned int m)
    2 {
    3     if (n < 1 || m < 1)
    4         return -1;
    5     int last = 0;
    6     for (int i = 2; i <= n; ++i)
    7         last = (last + m)%n;
    8     return last;
    9 }
  • 相关阅读:
    Android系统根文件系统目录结构
    4面 晶晨半导体 问题总结
    linux 工作队列
    Linux tasklet 的测试
    ArbotiX-M引脚说明
    locobot
    视频地址
    S1雷达ROS包更新指南
    rospy
    mx-28在 labview环境下的开发
  • 原文地址:https://www.cnblogs.com/happygirl-zjj/p/4629601.html
Copyright © 2011-2022 走看看