|
| 1 | +// A move consists of taking a point (x, y) and transforming it to either (x, x+y) or (x+y, y). |
| 2 | +// Given a starting point (sx, sy) and a target point (tx, ty), return True if and only if a sequence of moves exists to transform the point (sx, sy) to (tx, ty). Otherwise, return False. |
| 3 | +// |
| 4 | +// Examples: |
| 5 | +// Input: sx = 1, sy = 1, tx = 3, ty = 5 |
| 6 | +// Output: True |
| 7 | +// Explanation: |
| 8 | +// One series of moves that transforms the starting point to the target is: |
| 9 | +// (1, 1) -> (1, 2) |
| 10 | +// (1, 2) -> (3, 2) |
| 11 | +// (3, 2) -> (3, 5) |
| 12 | +// |
| 13 | +// Input: sx = 1, sy = 1, tx = 2, ty = 2 |
| 14 | +// Output: False |
| 15 | +// |
| 16 | +// Input: sx = 1, sy = 1, tx = 1, ty = 1 |
| 17 | +// Output: True |
| 18 | +// |
| 19 | +// Note: |
| 20 | +// |
| 21 | +// sx, sy, tx, ty will all be integers in the range [1, 10^9]. |
| 22 | + |
| 23 | +/** |
| 24 | + * @param {number} sx |
| 25 | + * @param {number} sy |
| 26 | + * @param {number} tx |
| 27 | + * @param {number} ty |
| 28 | + * @return {boolean} |
| 29 | + */ |
| 30 | + |
| 31 | +/** 1) Work Backwards (Naive Variant). Extremely slow. */ |
| 32 | +// Time O(max(tx,ty)). If say ty = 1, we could be subtracting tx times. |
| 33 | +// Space O(1) |
| 34 | +const reachingPoints1 = (sx, sy, tx, ty) => { |
| 35 | + while (tx >= sx && ty >= sy) { |
| 36 | + if (sx === tx && sy === ty) return true; |
| 37 | + if (tx > ty) tx -= ty; |
| 38 | + else ty -= tx; |
| 39 | + } |
| 40 | + return false; |
| 41 | +}; |
| 42 | + |
| 43 | +/** 2) Work Backwards (Modulo Variant)*/ |
| 44 | +// https://leetcode.com/problems/reaching-points/discuss/114856/JavaC%2B%2BPython-Modulo-from-the-End |
| 45 | +// |
| 46 | +// Time O(log(max(tx, ty))). The analysis is similar to the analysis of the Euclidean algorithm, and we assume that the modulo operation can be done in O(1) time. |
| 47 | +// Space O(1) |
| 48 | +// |
| 49 | +// If we start from sx, sy, it will be hard to find tx, ty. |
| 50 | +// If we start from tx, ty, we can find only one path to go back to sx, sy. |
| 51 | +// If cut down one by one at, it will be time limit exceeded. Remainder helps. |
| 52 | +// |
| 53 | +// If 2 target points are still bigger than 2 starting point, we reduce target points. |
| 54 | +// Check if we reduce target points to (x, y + kx) or (x + ky, y) |
| 55 | +const reachingPoints = (sx, sy, tx, ty) => { |
| 56 | + while (sx < tx && sy < ty) { |
| 57 | + if (tx < ty) ty %= tx; |
| 58 | + else tx %= ty; |
| 59 | + } |
| 60 | + return (sx === tx && sy <= ty && (ty - sy) % sx === 0) || |
| 61 | + (sy === ty && sx <= tx && (tx - sx) % sy === 0); |
| 62 | +}; |
0 commit comments