LeetCode Geometry 858 镜面反射

题目
有一个特殊的正方形房间,每面墙上都有一面镜子。除西南角以外,每个角落都放有一个接受器,编号为 0, 1,以及 2。
正方形房间的墙壁长度为 p,一束激光从西南角射出,首先会与东墙相遇,入射点到接收器 0 的距离为 q 。
返回光线最先遇到的接收器的编号(保证光线最终会遇到一个接收器)。

示例:
输入: p = 2, q = 1
输出: 2
解释: 这条光线在第一次被反射回左边的墙时就遇到了接收器 2 。
在这里插入图片描述

数学
我们把光线的运动拆分成水平和垂直两个方向来看。在水平和竖直方向,光线都在 0 到 p 之间往返运动,并且水平方向的运动速度是竖直方向的 p/q 倍。我们可以将光线的运动抽象成:
每过一个时间步,光线在水平方向从一侧跳动到另一侧(即移动 p 的距离),同时在竖直方向前进 q 的距离,如果到达了边界就折返。
由于接收器的位置在水平方向的两侧,因此只有当光线经过整数个时间步后,才有可能到达某一个接收器。而由于接收器的位置也在垂直方向的两侧,因此光线经过 k 个时间步后,它在竖直方向移动的总距离 kq 必须是 p 的倍数,才会碰到垂直方向的两侧。
因此,我们需要找到最小的 k 使得 kq 是 p 的倍数,并且根据 k 的奇偶性可以得知光线到达了左侧还是右侧;根据 kq / p 的奇偶性可以得知光线到达了上方还是下方,从而得知光线到达的接收器的编号。
显然,设 g = gcd(p, q) 为 p 和 q 的最大公约数,那么 s = pq / gcd(p, q) 是最小的同时整除 p 和 q 的数,即 p 和 q 的最小公倍数。因此 k 的值为 s / q = p / gcd(p, q)。

class Solution {
int mirrorReflection(int p, int q) {
        int g = gcd(p, q);
        p /= g; p %= 2;
        q /= g; q %= 2;

        if (p == 1 && q == 1) return 1;
        return p == 1 ? 0 : 2;
    }

    int gcd(int a, int b) {
        if (a == 0) return b;
        return gcd(b % a, a);
    }
}

复杂度分析
时间复杂度:O(logP),为求出最大公约数的时间复杂度。
空间复杂度:O(1)。

硬写!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值