主题 3:寻友之旅

661 阅读2分钟

当青训营遇上码上掘金

题目

小青要找小码去玩,他们的家在一条直线上,当前小青在地点 N ,小码在地点 K (0≤N , K≤100 000),并且小码在自己家原地不动等待小青。小青有两种交通方式可选:步行和公交。
步行:小青可以在一分钟内从任意节点 X 移动到节点 X-1 或 X+1
公交:小青可以在一分钟内从任意节点 X 移动到节点 2×X (公交不可以向后走) 请帮助小青通知小码,小青最快到达时间是多久?
输入: 两个整数 N 和 K
输出: 小青到小码家所需的最短时间(以分钟为单位)

作者:青训营官方账号
链接:juejin.cn/post/718775…
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

思路

典型的广度优先遍历的题。

为了方便讨论,我们把题中的时间叫做步数了哈。

假设小青当前来到了cur位置,那接下来她有3种行动方案

  • 步行,移动到cur-1位置
  • 步行,移动到cur+1位置
  • 公交,移动到2cur位置

如果采用深度优先的方式,在某个分支上可能会一直远离目标位置,也就没有停止的时刻了。但是,采用广度优先的方式什么时候停止呢?当然是第一个走到目标位置的可能方案就是最小步数啊。

我们现在假设,小码家在小青家右侧,这样我们只需要考虑小青向右到达目的地的情况。如果,输入与假设不符可以交换一下。

于是,我们可以构建一个节点,记录当前的位置,以及到达当前位置已经走的步数。

//    当前位置,以及走到这个位置走的步数
class Node{
    int postion;
    int step;
    public Node(int postion, int step) {
        this.postion = postion;
        this.step = step;
    }
}

有了这个节点,然后我们还需要准备一个队列,用来进行广度优先遍历的。每次从队列中取出来一个节点,分三种情况讨论下一步可以移动到的位置。如果,下一步是目标地址,我们就可以在当前的步数上加一返回。

代码

改进

在左右移动的过程中,我们可能走到重复的位置。举个例子, 初始我们在1位置,接下来按照三种情况我们可以走到如下三个位置0、2、2。这个时候,我们发现,2位置我们来到了两次,完全没有必要。因此,来到过的位置我们不需要再次计算了。于是,需要准备一个set,对走过的位置进行过滤。