Leetcode-780. 到达终点

链接

780. 到达终点

题目

给定四个整数 sx , sy ,tx 和 ty,如果通过一系列的转换可以从起点 (sx, sy) 到达终点 (tx, ty),则返回 true,否则返回 false。

从点 (x, y) 可以转换到 (x, x+y)  或者 (x+y, y)。

示例

示例 1:
输入: sx = 1, sy = 1, tx = 3, ty = 5
输出: true
解释:
可以通过以下一系列转换从起点转换到终点:
(1, 1) -> (1, 2)
(1, 2) -> (3, 2)
(3, 2) -> (3, 5)

示例 2:
输入: sx = 1, sy = 1, tx = 2, ty = 2 
输出: false

示例 3:
输入: sx = 1, sy = 1, tx = 1, ty = 1 
输出: true

说明

  • 1 <= sx, sy, tx, ty <= 10e9

思路

本题如果正向判断,从起点一直到终点,那么每一步将会出现多种情况,因为sx可以加上自身sx,也可以加上sy,同理,sy也可以加上自身sy,或者加上sx。如此一来,题目将变得比较复杂,因此,我们可以考虑反向推断。判断能否从终点到起点。

如果反向判断的话,会变成什么情况呢?拿示例 1:输入: sx = 1, sy = 1, tx = 3, ty = 5来说,终点为[3,5],那么终点前一步必然为[3,2],不可能再出现其他情况,而[3,2]的前一步呢?显然,必然为[1,2],也只存在一种情况,从以上例子可以看出,已知当前位置为[sx,sy],那么上一步的状态就可以唯一确定,分为以下三种情况:

  • 如果sx>sy,那么上一步为[sx-sy,sy],如[3,2]的上一步为[1,2].
  • 如果sy>sx,那么上一步为[sx,sy-sx], 如[3,5]的上一步为[3,2].
  • 如果sx=sy,由于sx和sy的值都要大于1,所以不存在[0,sy]或者[sx,0]的位置,此时[sx,sy]没有上一步,要么已经是起点,要么就永远到不了起点。

另外,对于上述的第1种和第2种情况,如果sx比sy大得多,例如[9,2]的情况,说明上一步是[7,2],[5,2],[3,2],[1,2]... 这种情况下我们就可以一次性判断前面多步,即:

  • 如果sx>sy,那么上一步为[sx%sy,sy],如[9,2]直接跳到[1,2]
  • 如果sy>sx,那么上一步为[sx,sy%sx], 如[3,17]直接跳到[3,2]
  • 如果sx=sy,和上述情况一致

我们从重点(tx,ty) 开始反向判断是否可以到达(sx,sy)的位置。只有当tx>起点sx,ty>起点sy,且tx≠ty的时候执行上述的过程,一直到tx、ty其中之一或者两个都到达了指定位置。

当上述条件不成立的时候,就可以进行最终的判断了:

  • 如果tx=sx且ty=sy,也就到达了起点位置,返回true。
  • 如果tx≠sx且ty≠sy,显然无法到达起点位置,返回false。
  • 如果tx=sx且ty≠sy,那么还需判断是否满足,ty>sy且(ty-sy)%sx=0,只有满足这个条件可以到达起始位置,例如sx,sy=[2,9] tx,ty=[2,5],满足9>5且(9-5)%2=0.
  • 如果tx≠sx且ty=sy,同理,还需判断是否满足tx>sx且(tx-sx)%sy=0.

通过以上判断,便可快速解决本题。

C++ Code

class Solution {
public:
    bool reachingPoints(int sx, int sy, int tx, int ty) {
        while (tx > sx && ty > sy && tx != ty) 
        {
            if (tx > ty) tx %= ty;
            else ty %= tx;
        }
        if (tx == sx && ty == sy) return true;
        else if (tx == sx) return ty > sy && (ty - sy) % tx == 0;
        else if (ty == sy) return tx > sx && (tx - sx) % ty == 0;
        else return false;
    }
};

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值