千问 LeetCode 2543. 判断一个点是否可以到达 Java实现
这道题的核心思路是从终点反向推导回起点,并利用最大公约数(GCD) 的性质来判定。
核心思路
从 (1, 1) 正向推导到 (targetX, targetY) 路径太多,不好下手。我们反过来想:从 (targetX, targetY) 能否通过逆操作回到 (1, 1)?
原操作(正向):
1. (x, y - x)
2. (x - y, y)
3. (2x, y)
4. (x, 2y)
对应的逆操作(反向):
1. (x, y + x)
2. (x + y, y)
3. (x/2, y) — 要求 x 为偶数
4. (x, y/2) — 要求 y 为偶数
数学结论
观察逆操作可以发现:
- 操作1和2(加法)不改变 x 和 y 的最大公约数(GCD)。
- 操作3和4(除以2)可能让 GCD 除以2。
因此,从 (targetX, targetY) 出发,无论怎么操作,最终得到的 GCD 一定是原始 GCD 不断除以2的结果。要能到达 (1, 1),最终 GCD 必须为 1。
结论:(targetX, targetY) 能到达 (1, 1) 的充要条件是:gcd(targetX, targetY) 是 2 的幂次方(即形如 1, 2, 4, 8, 16...)。
判断方法
一个数 g 是 2 的幂次方 ⇔ g & (g - 1) == 0(且 g > 0)。
Java 实现
class Solution {
public boolean isReachable(int targetX, int targetY) {
// 1. 计算最大公约数
int g = gcd(targetX, targetY);
// 2. 判断 g 是否为 2 的幂次方
return (g & (g - 1)) == 0;
}
// 辗转相除法求最大公约数
private int gcd(int a, int b) {
while (b != 0) {
int temp = b;
b = a % b;
a = temp;
}
return a;
}
}
代码说明
- gcd 方法:标准的欧几里得算法(辗转相除法),时间复杂度 O(log min(a,b))。
- g & (g - 1) == 0:这是判断一个正整数是否为 2 的幂次方的经典位运算技巧。例如 8 的二进制是 1000,8-1=7 是 0111,两者按位与结果为 0。
- 时间复杂度:O(log min(targetX, targetY)),完全能处理 10^9 级别的数据。
- 空间复杂度:O(1)。
示例验证
输入 GCD 是否为2的幂 结果
(6, 9) 3 否 (3不是2的幂) false
(4, 7) 1 是 (1 = 2⁰) true
(8, 12) 4 是 (4 = 2²) true
(10, 15) 5 否 false
这个解法简洁高效,是这道题的标准最优解。
更多推荐

所有评论(0)