题目概述
给定四个整数 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 <= 10^9
题目来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/reaching-points
解题分析
方法1:逆推法
已知结果坐标为 (tx, ty),并且结果坐标由前一个坐标变化而来,即 (tx, ty - tx) 或 (tx - ty, ty) ,而坐标的值的范围一定在 1 ~ 10^9 范围内,那么就不可能存在负数,因此我们只要对 tx 和 ty 的大小进行比较,就可以得到上一个坐标,然后再对上一个坐标重复如此的操作,就可以得到与 (sx, sy) 最近的坐标,进行比较就可以知道是否能到达终点。
时间复杂度:O(max(tx, ty)) 最坏情况为 2 和 10^9 时,进行 10^9 / 2 次遍历
空间复杂度:O(1)
class Solution {
public boolean reachingPoints(int sx, int sy, int tx, int ty) {
// 遍历
while(sx < tx && sy < ty){
// 对最大的数进行相减
if(tx > ty){
tx -= ty;
}
else{
ty -= tx;
}
}
return (sx == tx && ty >= sy && (ty - sy) % tx == 0) || (sy == ty && tx >= sx && (tx - sx) % ty == 0);
}
}
方法2:辗转相除法 + 逆推法
因为减的过程包括大量重复的相减过程,因此我们可以用取余的方式来代替相减,那么此时的问题就是余数可能会错过了起始值,但是因为另一个数还比起始值大,而这个数肯定是要从小的数加出来,而对方上一次比它小的数就是和它的余数,所以不用担心这个问题,大胆的去进行取余即可。
时间复杂度:O(log max(tx, ty))
空间复杂度:O(1)
class Solution {
public boolean reachingPoints(int sx, int sy, int tx, int ty) {
// 遍历
while(sx < tx && sy < ty){
// 对最大的数进行取余
if(tx > ty){
tx %= ty;
}
else{
ty %= tx;
}
}
return (sx == tx && ty >= sy && (ty - sy) % tx == 0) || (sy == ty && tx >= sx && (tx - sx) % ty == 0);
}
}