【程序员面试金典】面试题62. 圆圈中最后剩下的数字(模运算)

1. 题目

在这里插入图片描述

2. 思路

最优子问题:

  1. n 个数时,第一个删除的数的位置应当是 m%n (从零开始)
  2. 设 n-1 时,最后剩余的数的位置为 x (从零开始)
  3. n 个数时,删除第一个数后,剩余 n-1 个数,并从 m%n 开始进行删除,最后剩余的数为 (m%n + x) % n

PS: (m%n + x) % n < x (因为 (x + n) % n = x, 而 m%n < n)
所以删除m%n不会影响结果序号

化简公式:
(m%n + x) % n = (m%n%n + x%n) % n = (m%n + x%n) % n = (m + x) % n

3. 代码

class Solution {
    
    
    int f(int n, int m) {
    
    
        if (n == 1) // 当 n = 1 时,只有一个0
            return 0;
        int x = f(n - 1, m); // 计算从0开始,(n-1)个数时,最后剩余的数的位置
        return (m + x) % n; // n个数时删除的数的位置开始【(m%n + x) % n】
    }
public:
    int lastRemaining(int n, int m) {
    
    
        return f(n, m);
    }
};

4. 模运算的几个性质

m%n%n%n%n ... = m%n
(a%n + b%n) % n = (a + b) % n
(a*b) % n = (a%n * b%n) % n

如果a ≡ b (mod m),c ≡ d (mod m),那么
(1)a ± c ≡ b ± d (mod m);
(2)a * c ≡ b * d (mod m)。

余 定【数论】

猜你喜欢

转载自blog.csdn.net/Activity_Time/article/details/105236646