当青训营遇上码上掘金---寻友之旅

78 阅读3分钟
当青训营遇上码上掘金---寻友之旅

题目要求

小青要找小码去玩,他们的家在一条直线上,当前小青在地点 N ,小码在地点 K (0≤N , K≤100 000),并且小码在自己家原地不动等待小青。小青有两种交通方式可选:步行和公交。
步行:小青可以在一分钟内从任意节点 X 移动到节点 X-1 或 X+1
公交:小青可以在一分钟内从任意节点 X 移动到节点 2×X (公交不可以向后走)

请帮助小青通知小码,小青最快到达时间是多久?
输入: 两个整数 N 和 K
输出: 小青到小码家所需的最短时间(以分钟为单位)

package main

import (
	"fmt"
)

func main() {
	var n, k int
	fmt.Scan(&n, &k)
	fmt.Println(minSteps(n, k))
}

func minSteps(n, k int) int {
	steps := 0
	for n != k {
		if k > n {
			if k%2 == 0 {
				k /= 2
				steps++
			} else {
				k++
				steps++
			}
		} else {
			k++
			steps++
		}
	}
	return steps
}

上面的代码实现了一个名为minSteps的函数,它接受两个整数n和k作为输入,其中n是起点,k是目的地。它使用一个循环来重复直到n和k相等。在每次循环中,它检查k是否大于n。如果k大于n,它检查k是否是偶数。如果是,它将k除以2并增加步骤计数。如果k是奇数,它将k加1并增加步骤计数。如果k不大于n,它将k加1并增加步骤计数。该函数返回到达目的地所需的步骤数。

package main

import (
	"fmt"
	"queue"
)

func main() {
	var n, k int
	fmt.Scan(&n, &k)
	fmt.Println(minSteps(n, k))
}

func minSteps(n, k int) int {
	visited := make(map[int]bool)
	q := queue.New()
	q.Push(n)
	visited[n] = true
	steps := 0

	for q.Len() > 0 {
		size := q.Len()
		for i := 0; i < size; i++ {
			curr := q.Pop().(int)
			if curr == k {
				return steps
			}
			next := curr + 1
			if next <= 100000 && !visited[next] {
				q.Push(next)
				visited[next] = true
			}
			next = curr * 2
			if next <= 100000 && !visited[next] {
				q.Push(next)
				visited[next] = true
			}
		}
		steps++
	}
	return -1
}

这种实现使用队列数据结构和广度优先搜索算法来找到从n到k的最短路径。它首先将起点n推入队列并标记为已访问。然后进入一个循环,直到队列为空。在每次迭代中,它从队列中弹出当前位置,将其标记为已访问并增加步骤。然后将下一个可能的位置推入队列并将其标记为已访问。一旦到达目的地,它返回到达它所需要的步骤数。如果无法到达目的地,它返回-1。 这个代码里面用了一个队列,我们用队列来存储所有已经访问过的位置,每次从队列里面取出队首的位置,判断它可以到达的下一个位置,如果下一个位置没有被访问过,就加入队列并标记为已访问。如果下一个位置就是目的地,就返回步数。 这种实现虽然稍微复杂一点,但是它可以避免重复访问,更加高效,所以在复杂度较大的情况下更能适用。