Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Leetcode 2543. Check if Point Is Reachable #191

Open
Woodyiiiiiii opened this issue Jan 22, 2023 · 0 comments
Open

Leetcode 2543. Check if Point Is Reachable #191

Woodyiiiiiii opened this issue Jan 22, 2023 · 0 comments

Comments

@Woodyiiiiiii
Copy link
Owner

Woodyiiiiiii commented Jan 22, 2023

首先从这道题的原型780. Reaching Points讲起。

这道题如果从sx/sy出发,则时间复杂度完全取决于tx/ty,太大了。所以考虑从tx/ty出发。

那么要明白一个先决条件,tx/ty要变成sx/sy,是通过累加正数形成的,所以有:

  1. 如果当前sx==tx&&sy==ty则返回true
  2. 如果当前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)));
    }
}

再看这一题。

难点在于,看到这道题的后两个公式,要推出:

  1. tx和ty独立
  2. 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);
    }
}

这种解法的原理我还没理解。。看下面讲解悟一下吧。。

这种题型,思路一般是:

  1. 从targetX和targetY出发,看是否能到达x和y;因为从x和y出发就很难找到方向
  2. 观察移动公式,找到之间的关系

Tips:

  1. 找到规律
  2. bitCount函数 / (t & (t - 1) == 0)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant