【力扣每日一题】780. 到达终点

题目描述

给定四个整数 sx , sytxty,如果通过一系列的转换可以从起点 (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 <= 10^9

乍一看,这题目似乎还能理解。但要怎么下手呢,贪心吗,好像行不通,这不是什么最优化的问题,而是一个判断能不能的问题。我沉默了许久,还是没有想出什么好思路,暴力枚举肯定超时。于是,鉴于能力不足,我果断选择——看官方解法。


官方

这里对官方解法做了进一步的解释。

方法一:反向计算

如果从 (sx, sy)开始正向计算,则可能的情况非常多,会超出时间限制。注意到 sx, sy, tx, ty 都是正整数,因此对于给定的状态 (tx, ty),只有当 tx != ty时才存在上一个状态,且上一个状态唯一。

这里官方直接反手一个倒推,啊,根本不和你正面刚,这波就反向操作。我看了,顿时觉得自己一开始想的什么各种算法,都想小丑一样,貌似在动脑筋,其实没有卵用。确实,你从正面去思考,怎么从s达到最终的t,道路太多了,而且就像我前面分析的,也没有什么算法策略可以用。这种情况下,逆向思维的确就是一种优势,一种好的思想。

初看,感觉有点斐波那契的味道,但这不是你来我往,有来有回,而是没有规律随机的加法。用加法的角度看,很多选择,但从目标往回倒,用减法的角度看,就只有一种路可以走了。反之,如果这道题让你判断能不能从t减到s,那么就得从s开始倒推往上加了。

可能的情况如下:

如果 tx = ty,不存在上一个状态,状态 (tx, ty) 即为起点状态;

如果 tx > ty,则上一个状态是 (tx - ty, ty);

如果 tx < ty,则上一个状态是 (tx, ty - tx)。

注意到这里面在加的过程中,不可能出现相等的情况,如果x的值加到了y上,那么y更新后必定大于x,所以这个加的过程是此起彼伏的增长,x和y只能增加,不能减小。所以如果反向计算,一个状态的前一个状态(如果有),必定是大的那个数,减去小的那个数。如果出现相等,那么就表示这个状态不能再往回倒推了,只能是一个初始状态。

因此可以从 (tx, ty)开始反向计算,判断是否可以到达状态 (sx, sy)。当 tx > sx, ty > sy, tx != ty三个条件同时成立时,执行反向操作,每一步操作更新 (tx, ty) 的值,直到反向操作的条件不成立。

这里注意加上条件tx > sx 和 ty > sy,直接用while循环书写即可。

由于每一步反向操作一定是将 tx 和 ty 中的较大的值减小,因此当 tx > ty 时可以直接将 tx 的值更新为tx mod ty,当 tx < ty 时可以直接将 ty 的值更新为 ty mod tx。

这一步做了一个优化。本来一个值的更新,比如说是tx = tx-ty,但如果更新之后还是tx>ty,那么又要执行一遍tx=tx-ty,这样合起来相当于tx = tx - n*ty,直到tx<ty,有没有一种很熟悉的感觉,这不就是取模运算吗:x一直截去y,直到x小于y。所以这里是考虑x比y大很多的情况下,直接省去了中间的重复的减的过程。

当反向操作的条件不成立时,根据 tx 和 ty 的不同情况分别判断是否可以从起点转换到终点。

  1. 如果 tx = sx 且 ty = sy,则已经到达起点状态,因此可以从起点转换到终点。

  2. 如果 tx = sx 且 ty != sy,则 tx 不能继续减小,只能减小 ty,因此只有当 ty > sy且 (ty - sy) mod tx = 0 时可以从起点转换到终点。

  3. 如果 ty = sy 且 tx != sx,则 ty 不能继续减小,只能减小 tx,因此只有当 tx > sx 且 (tx - sx) mod ty = 0 时可以从起点转换到终点。

  4. 如果 tx != sx 且 ty != sy,则不可以从起点转换到终点。

这里是跳出了倒推循环做最后判断的时刻。首先我们得明白,跳出循环有几种情况:

  1. 我们先看最简单的tx=ty,如果出现这种情况,说明(tx,ty)倒推自然结束,与sx和sy无关,那么如果两个坐标不相等,自然是false,这是上面第4种情况。
    如果相等就是上面的第1种情况,不过这种情况十分巧合,就是一开始tx=sx且ty=sy, 完全没有经历倒推循环的操作,直接返回true。这种特殊情况也需要考虑,不然就会有且仅有一个测试用例卡着你过不去。

  2. 然后是剩余的情况,tx和ty中至少有一个(实际上也只能有一个)不大于初始值了。这种情况下,至少是等于初始值才有希望,如果小于初始值直接没戏,false,这也是上面第4种情况。

  3. 所以在其中一方等于初始值的情况下,这里用tx=sx举例,这时候ty>sy还成立,我们明白此时tx不可以再操作了,所以相让ty到sy,只能用ty去减tx,很自然地可以想到,只有在ty与sy的差值可以整除tx时,才可以让ty顺利倒推回sy,返回true。另一种ty=sy,tx>sx的思路一样,这两种对应上面的第2,3中情况。

java代码
//充分理解官方解法后,对代码做出了尽可能的精简。
class Solution {
    public boolean reachingPoints(int sx, int sy, int tx, int ty) {
      while(tx>sx && ty>sy && tx!=ty){
          if(tx>ty) tx = tx%ty;
          else ty = ty%tx;
      }

      if(tx==sx && ty==sy) return true;
      if(tx==sx && ty>sy && (ty-sy)%tx==0) return true;
      if(ty==sy && tx>sx && (tx-sx)%ty==0) return true;
      return false;
    }
}

后记:

还是要好好思考。题目解析读起来还不算难,但怎么想到这个解法就很难。

多做题,多总结还是王道。

一切奇思妙想的算法输出的前提,都是大量做题经验的优质输入。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值