Leetcode 2543. Check if Point Is Reachable
Woodyiiiiiii opened this issue · comments
首先从这道题的原型780. Reaching Points讲起。
这道题如果从sx/sy出发,则时间复杂度完全取决于tx/ty,太大了。所以考虑从tx/ty出发。
那么要明白一个先决条件,tx/ty要变成sx/sy,是通过累加正数形成的,所以有:
- 如果当前
sx==tx&&sy==ty
则返回true - 如果当前
sx<tx || sy < ty
则返回false
接下来,考虑如何处理tx/ty的进程呢?注意到两个变量之间的变化,是通过大的数减去小的一方来实现的,加上目标值sx/sy,所以我们可以直接使用/和%得到sx/sy相同层级的tx/ty,即:以tx举例,假如tx>ty(比如tx=100000,ty=1),那么用sx/ty
得到sx=k*ty+?
中的k,然后通过tx%ty
填充?
,最后还要考虑循环的情况(比如[9,5,12,8]),如此以来直接得到公式reachingPoints(sx, sy, (sx / ty) * ty + tx % ty == tx ? sx - 1 : (sx / ty) * ty + tx % ty, ty)
。
class Solution {
public boolean reachingPoints(int sx, int sy, int tx, int ty) {
if (tx < sx || ty < sy) return false;
if (tx == sx && ty == sy) return true;
return (tx > ty && reachingPoints(sx, sy, (sx / ty) * ty + tx % ty == tx ? sx - 1 : (sx / ty) * ty + tx % ty, ty)
|| (tx <= ty && reachingPoints(sx, sy, tx, (sy / tx) * tx + ty % tx == ty ? sy - 1 : (sy / tx) * tx + ty % tx)));
}
}
再看这一题。
难点在于,看到这道题的后两个公式,要推出:
- tx和ty独立
- tx和ty如果有一个是2的次数,则他们有一个能到达1,这样就可以通过相减,直接达到sx和sy
所以,关键是找到x和y能否通过变化公式1和2,满足上述条件2。
class Solution {
public boolean isReachable(int targetX, int targetY) {
if (targetX < 1 || targetY < 1) {
return false;
}
if (Integer.bitCount(targetX) == 1 || Integer.bitCount(targetY) == 1) {
return true;
}
return isReachable(targetX - targetY, targetY) || isReachable(targetX, targetY - targetX);
}
}
这道题还有更简便的做法,也是扩展欧几里得公式。因为ax+by=gcd(a,b),所以我们只要找到gcd是否有2的次数即可。
class Solution {
public boolean isReachable(int targetX, int targetY) {
int gcd = gcd(targetX, targetY);
return Integer.bitCount(gcd) == 1; // gcd & (gcd - 1) == 0
}
private int gcd(int a, int b) {
if (b == 0) return a;
return gcd(b, a % b);
}
}
这种解法的原理我还没理解。。看下面讲解悟一下吧。。
这种题型,思路一般是:
- 从targetX和targetY出发,看是否能到达x和y;因为从x和y出发就很难找到方向
- 观察移动公式,找到之间的关系
Tips:
- 找到规律
- bitCount函数 / (t & (t - 1) == 0)
- 2543. Check if Point Is Reachable
- https://leetcode.com/problems/check-if-point-is-reachable/solutions/3082073/java-c-python-1-line-gcd-solution/
- https://leetcode.com/problems/check-if-point-is-reachable/solutions/3082147/c-java-python-gcd/
- https://leetcode.cn/problems/check-if-point-is-reachable/solutions/2072955/c-by-muriyatensei-4r2t/
- https://leetcode.cn/problems/check-if-point-is-reachable/solutions/2073036/wen-ti-zhuan-huan-gcdju-ti-gou-zao-fang-0plx0/