leetcode
leetcode 2201 ~ 2250
判断一个点是否可以到达

判断一个点是否可以到达

难度:

标签:

题目描述

There exists an infinitely large grid. You are currently at point (1, 1), and you need to reach the point (targetX, targetY) using a finite number of steps.

In one step, you can move from point (x, y) to any one of the following points:

  • (x, y - x)
  • (x - y, y)
  • (2 * x, y)
  • (x, 2 * y)

Given two integers targetX and targetY representing the X-coordinate and Y-coordinate of your final position, return true if you can reach the point from (1, 1) using some number of steps, and false otherwise.

 

Example 1:

Input: targetX = 6, targetY = 9
Output: false
Explanation: It is impossible to reach (6,9) from (1,1) using any sequence of moves, so false is returned.

Example 2:

Input: targetX = 4, targetY = 7
Output: true
Explanation: You can follow the path (1,1) -> (1,2) -> (1,4) -> (1,8) -> (1,7) -> (2,7) -> (4,7).

 

Constraints:

  • 1 <= targetX, targetY <= 109

代码结果

运行时间: 21 ms, 内存: 15.9 MB


/*
 * 题目思路:
 * 与Java解法相同,利用Java Stream来进行操作
 * 虽然Stream在此题目中不是最优的解决方案,但它展示了一种使用lambda表达式和流的方式
 */
import java.util.stream.Stream;
public class Solution {
    public boolean canReach(int targetX, int targetY) {
        return Stream.iterate(new int[]{targetX, targetY}, p -> p[0] > 1 && p[1] > 1,
                p -> p[0] > p[1] ? new int[]{p[0] % p[1], p[1]} : new int[]{p[0], p[1] % p[0]})
                .anyMatch(p -> (p[0] == 1 && p[1] > 0) || (p[1] == 1 && p[0] > 0));
    }
}

解释

方法:

该题解使用了逆向思维的深度优先搜索(DFS)方法。从目标点 (targetX, targetY) 开始,尝试反向追溯到起点 (1, 1)。反向操作包括:如果当前坐标的 x 或 y 是偶数,则将其除以 2;如果坐标 x 和 y 不相等,则尝试通过减法操作逆向推回。这里的思路是从目标点反推到初始点,而非正向从起点搜索到终点,因为反向操作可以更直接地缩小搜索空间。递归中,如果 x 和 y 相等而且都是奇数,则无法继续操作,因为不可能通过以上操作生成两个相等的奇数。最终,如果能反向递归到 (1, 1),说明目标点可达,返回 true;否则返回 false。通过使用 @cache 装饰器,优化了重复子问题的求解过程,提高了效率。

时间复杂度:

O(log(max(targetX, targetY)))

空间复杂度:

O(log(max(targetX, targetY)))

代码细节讲解

🦆
为什么在递归函数中,对 x 和 y 都是偶数的情况没有同时尝试 x 和 y 除以 2 的操作?
在递归函数中,当 x 和 y 都是偶数时,实际上对 x 或 y 进行除以 2 的操作是互相独立的。这意味着,在任何给定的递归步骤中,我们可以选择对 x 或 y 进行操作,而不会遗漏可能的路径。由于这两种操作是条件互斥的(即进行一种操作后,另一种操作的条件就不再满足),因此在一个递归调用中只需要选择一种操作。此外,同时对 x 和 y 进行除以 2 的操作在逻辑上不会同时出现,因为我们总是可以通过多次递归来达到相同的结果。
🦆
在递归函数中,如果 x 和 y 都是奇数且相等时返回 false,这种情况下是否有可能通过某种组合的操作到达其他状态?
当 x 和 y 都是奇数且相等时,无法通过给定的操作(除以 2 或减法)来改变它们的状态,使得其中一个成为偶数或不相等。因为减法操作 (x - y, y) 或 (x, y - x) 在 x 和 y 相等时不会改变任何值,而除以 2 的操作也无法应用于奇数。因此,如果 x 和 y 在任何递归步骤中都是奇数且相等,就无法通过进一步的操作到达 (1, 1)。
🦆
在递归中使用 @cache 来优化性能,那么这种方法的空间复杂度是多少?
使用 @cache 装饰器可以缓存递归函数的中间结果,避免重复计算相同参数的结果,从而显著提高效率。空间复杂度主要取决于缓存中存储的不同参数组合的数量。在最坏情况下,每个参数 (x, y) 可能都是从 targetX 和 targetY 出发可能达到的任何值。因此,空间复杂度依赖于从目标点到起点可能的路径数量。在这种情况下,空间复杂度可能接近 O(targetX * targetY),因为每个点可能至少被访问一次。但实际上,由于操作的限制性,访问的状态通常远少于此理论上限。

相关问题