Woodyiiiiiii / LeetCode

My private record of Leetcode solution

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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,是通过累加正数形成的,所以有:

  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)