题目: https://leetcode.com/problems/reaching-points/
难度: Hard
题意:
- 给定一个点对(x,y),每次操作可以变换成(x,x+y)或者(x+y,y)
- 给定两个点对(sx, sy),和(tx, ty),问能否通过任意次操作,使前一个点对可以变换成后一个点对
思路:
- 我们反正来,如果得到一个点对(x,y),最有可能是从哪些点对来的
- 假设tx<ty,反之亦然
- 那么点对可以从(tx,ty),(tx, ty-tx),(tx,ty-k*tx)。。。得来的
- 我们可以得出一个递归方式
- 如果sx>tx,直接返回false,因为sx不管怎么变换,都不能比sx小
- 如果sx=tx,判断(ty-sy)是否不小于0,并且可以被sx整除
- 如果sx<tx,那么我们需要判断(sx, sy)和(tx, ty % tx)是否可以变换
- 这个算法叫做辗转相除法,也叫欧几里得算法,计算最大公约数也是这个算法
解法:
class Solution {
private boolean solve(int sx, int sy, int tx, int ty) {
if (tx < ty) {
if (tx < sx) {
return false;
}
if (tx == sx) {
if (ty >= sy && (ty - sy) % sx == 0) {
return true;
} else {
return false;
}
}
return solve(sx, sy, tx, ty % tx);
} else {
if (ty < sy) {
return false;
}
if (ty == sy) {
if (tx >= sx && (tx - sx) % sy == 0) {
return true;
} else {
return false;
}
}
return solve(sx, sy, tx % ty, ty);
}
}
public boolean reachingPoints(int sx, int sy, int tx, int ty) {
return solve(sx, sy, tx, ty);
}
}