链接
题目
给定四个整数 sx , sy ,tx 和 ty,如果通过一系列的转换可以从起点 (sx, sy) 到达终点 (tx, ty),则返回 true,否则返回 false。
从点 (x, y) 可以转换到 (x, x+y) 或者 (x+y, y)。
示例
示例 1:
输入: sx = 1, sy = 1, tx = 3, ty = 5
输出: true
解释:
可以通过以下一系列转换从起点转换到终点:
(1, 1) -> (1, 2)
(1, 2) -> (3, 2)
(3, 2) -> (3, 5)示例 2:
输入: sx = 1, sy = 1, tx = 2, ty = 2
输出: false示例 3:
输入: sx = 1, sy = 1, tx = 1, ty = 1
输出: true
说明
1 <= sx, sy, tx, ty <= 10e9
思路
本题如果正向判断,从起点一直到终点,那么每一步将会出现多种情况,因为sx可以加上自身sx,也可以加上sy,同理,sy也可以加上自身sy,或者加上sx。如此一来,题目将变得比较复杂,因此,我们可以考虑反向推断。判断能否从终点到起点。
如果反向判断的话,会变成什么情况呢?拿示例 1:输入: sx = 1, sy = 1, tx = 3, ty = 5来说,终点为[3,5],那么终点前一步必然为[3,2],不可能再出现其他情况,而[3,2]的前一步呢?显然,必然为[1,2],也只存在一种情况,从以上例子可以看出,已知当前位置为[sx,sy],那么上一步的状态就可以唯一确定,分为以下三种情况:
- 如果sx>sy,那么上一步为[sx-sy,sy],如[3,2]的上一步为[1,2].
- 如果sy>sx,那么上一步为[sx,sy-sx], 如[3,5]的上一步为[3,2].
- 如果sx=sy,由于sx和sy的值都要大于1,所以不存在[0,sy]或者[sx,0]的位置,此时[sx,sy]没有上一步,要么已经是起点,要么就永远到不了起点。
另外,对于上述的第1种和第2种情况,如果sx比sy大得多,例如[9,2]的情况,说明上一步是[7,2],[5,2],[3,2],[1,2]... 这种情况下我们就可以一次性判断前面多步,即:
- 如果sx>sy,那么上一步为[sx%sy,sy],如[9,2]直接跳到[1,2]
- 如果sy>sx,那么上一步为[sx,sy%sx], 如[3,17]直接跳到[3,2]
- 如果sx=sy,和上述情况一致
我们从重点(tx,ty) 开始反向判断是否可以到达(sx,sy)的位置。只有当tx>起点sx,ty>起点sy,且tx≠ty的时候执行上述的过程,一直到tx、ty其中之一或者两个都到达了指定位置。
当上述条件不成立的时候,就可以进行最终的判断了:
- 如果tx=sx且ty=sy,也就到达了起点位置,返回true。
- 如果tx≠sx且ty≠sy,显然无法到达起点位置,返回false。
- 如果tx=sx且ty≠sy,那么还需判断是否满足,ty>sy且(ty-sy)%sx=0,只有满足这个条件可以到达起始位置,例如sx,sy=[2,9] tx,ty=[2,5],满足9>5且(9-5)%2=0.
- 如果tx≠sx且ty=sy,同理,还需判断是否满足tx>sx且(tx-sx)%sy=0.
通过以上判断,便可快速解决本题。
C++ Code
class Solution {
public:
bool reachingPoints(int sx, int sy, int tx, int ty) {
while (tx > sx && ty > sy && tx != ty)
{
if (tx > ty) tx %= ty;
else ty %= tx;
}
if (tx == sx && ty == sy) return true;
else if (tx == sx) return ty > sy && (ty - sy) % tx == 0;
else if (ty == sy) return tx > sx && (tx - sx) % ty == 0;
else return false;
}
};