LeetCode算法题-镜面反射(Mirror Reflection)

1. 题目:

有一个四面墙都有镜子的特殊正方形房间。除了西南角之外,其他三个角都有接收器,编号为0, 1, 2。方形房间的墙长度为p,有一束射线从西南角照射到东面的墙上,到墙角0的距离为q。请找出射线遇到的第一个接收器的编号(可以保证射线最终会遇到一个接收器)。

例如:

输入:p = 2, q = 1

输出:2

解释:当射线第一次反射到左边墙上的时候,会遇到接收器2。

LeetCode算法题-镜面反射(Mirror Reflection)_第1张图片

注意:

1. 1 <= p <= 1000

2. 0 <= q <= p

 

2. 解释:

这道题如果直接硬解会比较复杂,可以用多次空间想象降低复杂度。

第一步:将射线照射方向直线延长,按照横向和纵向展开方形房间,如下图:

LeetCode算法题-镜面反射(Mirror Reflection)_第2张图片

将射线直线延长后,遇到第一个接收器时,可以得到边长x,y的三角形,该三角形是通过边长p,q的三角形延长得到的,所以x/p = y/q,因为x/p为整数,所以y/q也为整数,又因为y同时也是方形边长p的整数倍,所以设存在整数变量n,y=np,找出最小值n满足np是q的整数倍即可,即可得到公式:

n = 1;  while( p*n % q != 0) n += 1 ;

通过上面的公式可以得出满足q和p最小公倍数y的变量n,y=np, x=(np/q)* p, 记住n、x和y的值对后面的推导很关键。

 

第二步:只在横向方向展开方形房间,射线会发生反射,如下图:

LeetCode算法题-镜面反射(Mirror Reflection)_第3张图片

将方形房间按照横向展开,射线只在横轴发生发射,接收器0在下方,接收器1和2在上方,当射线反射2次、4次、6次、8次等2的倍数次才能遇到在下方的接收器0,那么反射的次数乘以方形边长p即等于第一步纵向展开的y,又因为第一步已经推导出了y=np,所以n即为反射的次数,当n为偶数时,射线会遇到接收器0,可得到公式:

if( n % 2 ==0 ) return 0;

 

第三步:还是只在横向方向展开方向房间,如下图:

LeetCode算法题-镜面反射(Mirror Reflection)_第4张图片

当射线遇到接收器1时,横向距离x为X1,观察图可知X1是方形边长p的奇数倍,当射线遇到接收器2时,横向距离x为X2,观察图可知X2为方形边长p的偶数倍,第一步中已得到x=(np/q)* p,那么x的方形边长p的倍数为:(np/q)* p / p = np/q,可得到公式:

int r = p*n /q; 

if(r % 2 ==0) return 2; 

if(r % 2 ==1) return 1;

 

3. 总结:

该题考察的是对空间想象的能力,通过上面三步对方形房间的空间展开,很大程度降低了解题难度,综合每步得到的公式,汇总可以得到该题的正确答案:

public int mirrorReflection(int p, int q) {
 
    int n = 1;
    while( p*n % q != 0) n += 1 ;
    if( n % 2 ==0 ) return 0;
	
    int r =  p*n /q;
    if(r % 2 ==0) return 2;
    if(r % 2 ==1) return 1;
    
    return -1;
}

 

你可能感兴趣的:(算法题)