【程序员面试金典】面试题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)。

余 定【数论】

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值