LeetCode 镜面反射(图解,妙~)

版权声明:本文为博主原创文章,博客地址:https://blog.csdn.net/qq_41855420,未经博主允许不得转载。 https://blog.csdn.net/qq_41855420/article/details/91045415

有一个特殊的正方形房间,每面墙上都有一面镜子。除西南角以外,每个角落都放有一个接受器,编号为 0, 1,以及 2。

正方形房间的墙壁长度为 p,一束激光从西南角射出,首先会与东墙相遇,入射点到接收器 0 的距离为 q 。

返回光线最先遇到的接收器的编号(保证光线最终会遇到一个接收器)。

示例:

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

在这里插入图片描述
提示:

1 <= p <= 1000
0 <= q <= p

\color{blue}思路分析: 这道题比较容易想到的方法是直接计算每次的位置。由于镜子是在三个角,因此我们只要考虑左右反射即可,并且光线由左向右发射时,y轴(纵向)增量为q,光线由右向左发射时,y轴(纵向)增量为 -q。蛋式有两种比较特殊的情况:
第一种:光线由右向左发射时,会碰到上边界,从而再反射到左边。
在这里插入图片描述
第二种:光线由左向右发射时,会碰到下边界,从而再反射到右边。
在这里插入图片描述

class Solution {
public:
    int mirrorReflection(int p, int q) {
        int x = 0, y = 0;
        int direction = 1;//大于零说明是由左向右发射,小于零是由右向左发射
        while (true){
            //x坐标:由于光线在两个前面反射,所以x在[0, p]互相转换
            if (x == 0){
                x = p;
            }
            else{
                x = 0;
            }
            //y坐标:分反射方向变换
            if (direction > 0){
                //光线由左向右发射
                y += q;//y轴增量为 q
                if (y > p){
                    //第一种特殊情况:y超过了p,经过上边界进行反射回到左侧
                    direction = -1;
                    y = p - (y - p);
                }
            }
            else{
                //光线由右向左发射
                y -= q;//y轴增量为 -q
                if (y < 0){
                    //第二种特殊情况:y出现负值,经过下边界进行反射回到右侧
                    direction = 1;
                    y = -y;
                }
            }
            //下面是判断是否到达了镜子的位置
            if (y == p){
                if (x == 0){
                    return 2;
                }
                else{
                    return 1;
                }
            }
            if (y == 0 && x == p){
                return 0;
            }
        }
    }
};

在这里插入图片描述
也可以直接根据p、q的奇偶性直接判断第一个到达的镜子。
首先从最简单的情况开始分析,当p和q相等的时候,那么激光直接到达接收器1,当 p/q = 2 的时候,就如例子中所示,经过右边的镜面反射后到达左上角的接受器2。那么我们再来考虑下这三种情况 p/q = 3, p/q = 4, p/q = 3/2,并画出折射情况如下所示:
在这里插入图片描述
我们知道激光遇到镜面是会发生折射的,但是假如没有镜面,就会仍然沿直线前进,那么对于 p/q = 3 时,若我们在右边增加大小相同的2个房间,则激光会到达右上角,由于第二个房间和原始房间是镜面对称的,而第三个房间和第二个房间也是镜面对称的,则第三个房间和原始房间就是一样的了,那么就可以假设一下,奇数房间和原始房间的布局相同。再来看上图中的 p/q = 4 时,我们在右边复制了三个房间,在第四个房间的时候,激光到达了右上角,而第偶数个房间的布局是跟原始房间称镜面反射的,则就是接受器2了。其实有些时候,我们不止要在右边复制房间,还需要在上面复制房间,比如当 p/q = 3/2 时,我们需要复制出一个 2x3 大小的矩阵出来,在水平方向共有三个房间,是奇数则水平方向和原始房间布局一致,但是竖直方向也复制了房间,那么竖直方向有偶数个房间,则竖直方向和原始房间成镜面反射,则最右上角为接收器0。

分析到这里,我们应该已经能总结出规律如下了:

p为奇数,q为奇数时,到达接收器1。
p为奇数,q为偶数时,到达接收器0。
p为偶数,q为奇数时,到达接收器2。
class Solution {
public:
    int mirrorReflection(int p, int q) {
        //如果p、q同时为偶数,则可以同时缩小为原来的二分之一,并不影响结果
        while (p % 2 == 0 && q % 2 == 0) {
            p /= 2; 
            q /= 2;
        }
        //经过上面的缩小,则p、q至少有一个为奇数
        if (p % 2 == 0) {
            return 2;
        }
        else if (q % 2 == 0) {
            return 0;
        }
        else {
            return 1;
        }
    }
};

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_41855420/article/details/91045415