您的位置:首页 > 其它

Weekly Contest 71 leetcode 780. Reaching Points

2018-02-11 15:12 274 查看
A move consists of taking a point 
(x, y)
 and transforming it to either 
(x,
x+y)
 or 
(x+y, y)
.

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
.
Examples:
Input: sx = 1, sy = 1, tx = 3, ty = 5
Output: True
Explanation:
One series of moves that transforms the starting point to the target is:
(1, 1) -> (1, 2)
(1, 2) -> (3, 2)
(3, 2) -> (3, 5)

Input: sx = 1, sy = 1, tx = 2, ty = 2
Output: False

Input: sx = 1, sy = 1, tx = 1, ty = 1
Output: True


Note:
sx, sy, tx, ty
 will all be integers in the range 
[1,
10^9]
.

这道题主要是要找到时间复杂度较小的思路。我无论怎么做,要么TLE,要么StackOverFlow,无奈,只能看看solutions,看看大神的解法。
solutions:https://leetcode.com/problems/reaching-points/solution/,solutions 前几个给的都是TLE的解法,即不能通过测试用例。主要是看最后一个AC的解法。


Approach #1: Exhaustive Search [Time Limit Exceeded]

class Solution {
public boolean reachingPoints(int sx, int sy, int tx, int ty) {
if (sx > tx || sy > ty) return false;
if (sx == tx && sy == ty) return true;
return reachingPoints(sx+sy, sy, tx, ty) || reachingPoints(sx, sx+sy, tx, ty);
}
}
Complexity Analysis

Time Complexity: O(2^{tx
+ ty})O(2​tx+ty​​),
a loose bound found by considering every move as 
(x, y) -> (x+1, y)
or 
(x,
y) -> (x, y+1)
 instead.

Space Complexity: O(tx
* ty)O(tx∗ty),
the size of the implicit call stack.


Approach #2: Dynamic Programming [Time Limit Exceeded]

Intuition and Algorithm

As in Approach #1, we search the children of every point recursively, except we use a set 
seen
 so
that we don't repeat work.
import java.awt.Point;

class Solution {
Set<Point> seen;
int tx, ty;

public boolean reachingPoints(int sx, int sy, int tx, int ty) {
seen = new HashSet();
this.tx = tx;
this.ty = ty;
search(new Point(sx, sy));
return seen.contains(new Point(tx, ty));
}

public void search(Point P) {
if (seen.contains(P)) return;
if (P.x > tx || P.y > ty) return;
seen.add(P);
search(new Point(P.x + P.y, P.y));
search(new Point(P.x, P.x + P.y));
}
}


Complexity Analysis

Time Complexity: O(tx
* ty)O(tx∗ty),
as at most 
tx * ty
 points are searched once per point.

Space Complexity: O(tx
* ty)O(tx∗ty),
the size of the implicit call stack.


Approach #3: Work Backwards (Naive Variant) [Time Limit Exceeded]

Intuition

Every parent point 
(x, y)
 has two children, 
(x,
x+y)
 and 
(x+y, y)
. However, every point 
(x,
y)
 only has one parent candidate 
(x-y, y)
 if 
x
>= y
, else 
(x, y-x)
. This is because we never have points with negative coordinates.

Looking at previous successive parents of the target point, we can find whether the starting point was an ancestor. For example, if the target point is 
(19,
12)
, the successive parents must have been 
(7, 12)
(7,
5)
, and 
(2, 5)
; so 
(2,
5)
 is a starting point of 
(19, 12)
.

Algorithm

Repeatedly subtract the smaller of 
{tx, ty}
 from the larger of 
{tx,
ty}
. The answer is true if and only if we eventually reach 
sx, sy
.
class Solution {
public boolean reachingPoints(int sx, int sy, int tx, int ty) {
while (tx >= sx && ty >= sy) {
if (sx == tx && sy == ty)
return true;
if (tx > ty) tx -= ty;
else ty -= tx;
}
return false;
}
}


Complexity Analysis

Time Complexity: O(\max(tx, ty))O(max(tx,ty)).
If say 
ty = 1
, we could be subtracting 
tx
 times.

Space Complexity: O(1)O(1).


Approach #4: Work Backwards (Modulo Variant) [Accepted]

Intuition

As in Approach #3, we work backwards to find the answer, trying to transform the target point to the starting point via applying the parent operation 
(x,
y) -> (x-y, y) or (x, y-x)
 [depending on which one doesn't have negative coordinates.]

We can speed up this transformation.

Algorithm

当 
tx > ty
  时,找父母的操作就是 
tx
 - 
ty
,
直到 
tx = tx % ty
 为止。当 
tx
> ty
 和 
ty > sy
 都满足时,我们可以使用 
tx
%= ty
 来代替 
while
tx > ty: tx -= ty
 ,会更快。

当 
tx > ty 且 ty = sy
  时,我们知道 
ty
 不能再减了,所以只有 
tx
 会改变,并且只会通过
一步步地减去
ty
  来改变。所以,使用 
(tx
- sx) % ty == 0
 会更高效。

ty > tx
  的情形同理。可以一直这样做,直到 
tx
== ty
, 此时不需要再做 move 了。
class Solution {
public boolean reachingPoints(int sx, int sy, int tx, int ty) {
while (tx >= sx && ty >= sy) {
if (tx == ty) break;
if (tx > ty) {
if (ty > sy) tx %= ty;
else return (tx - sx) % ty == 0;
} else {
if (tx > sx) ty %= tx;
else return (ty - sy) % tx == 0;
}
}
return (tx == sx && ty == sy);
}
}


Complexity Analysis

Time Complexity: O(\log(\max{(tx, ty)}))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)O(1) time.

Space Complexity: O(1)O(1).
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: