每日一题 780 到达终点

780. 到达终点

给定四个整数 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 + sy, sy)或者(sx, sx + sy);

我们可以写出:

1
2
3
4
5
6
7
8
class Solution {
public:
bool reachingPoints(int sx, int sy, int tx, int ty) {
if(sx > tx || sy > ty) return false;
if(sx == tx && sy == ty) return true;
return reachingPoints(sx + sy, sy, tx, ty) || reachingPoints(sx, sx + sy, tx, ty);
}
};

然后我们发现栈溢出了,这里可以用long解决,但是肯定超时。

那既然正着求会栈溢出,我们可不可以倒着求呢?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Solution {
public:
bool reachingPoints(int sx, int sy, int tx, int ty) {
if(tx < sx || ty < sy) return false;
while(tx > 0 && ty > 0){
if(sx == tx && sy == ty){
return true;
}
if(tx > ty){
tx -= ty;
}else{
ty -= tx;
}
}
return false;
}
};

发现还是超时了,还有哪里可以改进呢,我们发现在tx > ty时,我们不止可以一次减去ty,可以减去最大可以减去,ty > tx处同理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Solution {
public:
bool reachingPoints(int sx, int sy, int tx, int ty) {
if(tx < sx || ty < sy) return false;
while(tx > 0 && ty > 0){
if(sx == tx && sy == ty){
return true;
}
if(tx > ty){
//tx - sx是目标与起始值在x的差距,我们需要一次减去n * ty达到快速逼近sx的目的
tx -= max((tx - sx)/ty, 1) * ty;
}else{
//ty - sy是目标与起始值在y的差距,我们需要一次减去n * tx达到快速逼近sy的目的
ty -= max((ty - sy)/tx, 1) * tx;
}
}
return false;
}
};

这样就可以解了。