题目描述
给定四个整数 sx
,sy
,tx
和 ty
,如果通过一系列的转换可以从起点 (sx, sy)
到达终点 (tx, ty)
,则返回 true
,否则返回 false
。
从点 (x, y)
可以转换到 (x, x+y)
或者 (x+y, y)
。
样例
输入:sx = 1, sy = 1, tx = 3, ty = 5
输出:true
解释:
可以通过以下一系列转换从起点转换到终点:
(1, 1) -> (1, 2)
(1, 2) -> (3, 2)
(3, 2) -> (3, 5)
输入:sx = 1, sy = 1, tx = 2, ty = 2
输出:false
输入:sx = 1, sy = 1, tx = 1, ty = 1
输出:true
限制
1 <= sx, sy, tx, ty <= 10^9
算法
(数学,辗转相除法) $O(\log (\max(tx, ty)))$
- 试图从点
(sx, sy)
向点(tx, ty)
进行转换非常不便,因为不确定每次要进行哪种转换,但从点(tx, ty)
向(sx, sy)
转换就很方便,因为逆向转换总是确定的。 - 暴力的来做,我们每次让
(tx, ty)
中较大的数字减去较小的数字,便得到一组新的(tx, ty)
。我们仅需要判断是否经过若干次转换可以到达点(sx, sy)
。 - 由于数据范围很大,暴力的做法会超时。我们可以考虑用取模操作来替代减法。如果当前的
tx > sx
并且ty > sy
,则我们令较大的数字模掉较小的数字。循环结束后,如果tx < sx
或者ty < sy
,则不可能到达;如果tx == sx
,则我们判断ty
与sy
的差值是否能由sx
拼凑而成;同理,如果ty == sy
,则我们判断tx
与sx
的差值是否能由sy
拼成。
时间复杂度
- 取模操作最多进行 $O(\log (\max(tx, ty)))$ 次。
空间复杂度
- 仅需要常数的额外空间。
C++ 代码
class Solution {
public:
bool reachingPoints(int sx, int sy, int tx, int ty) {
while (tx > sx && ty > sy) {
if (tx < ty) ty %= tx;
else tx %= ty;
}
if (tx < sx || ty < sy)
return false;
if (sx == tx)
return (ty - sy) % sx == 0;
return (tx - sx) % sy == 0;
}
};
哇 好清晰
tql