当青训营遇上码上掘金——寻友之旅(GO)| 青训营笔记

73 阅读2分钟

当青训营遇上码上掘金

题目:

主题 3:寻友之旅

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

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

解题思路:

  1. 我们需要使用一个队列wait来存储待处理的结点,由于采用的是广度优先搜索的思路,因此每当搜索到一个结点时,都会将其入队,然后再将元素(点)依次出队来搜索该元素(点)可以到达的位置,在搜索过程中,会更新dist和flag数组中的相关值。

  2. 为了解决同一个点重复遍历的情况,我们需要flag数组,数组中每个元素代表当前序号的结点是否已经过队列处理。初始化时,将每个元素赋值为0,表示尚未处理该结点;等结点进入队列时,将值更新为1。

  3. 需要考虑两种情况, N > K 时,公交车只能向前走, 所以只能步行,消费为1。考虑 N < K的情况,则采用bfs算法遍历。

算法设置:

  1. 先定义一个dist数组,数组中每个元素存储小青到该结点的最短时间,初始化为最大值
  2. 再定义一个flag数组,记录每个位置是否被访问过,初始化为0,访问过置1
  3. 定义一个wait数组,记录所有小青可以访问的位置,初始化为0
  4. 将小青的位置加入到wait数组中,并将其flag置为1,dist置为0
  5. 从wait数组中弹出一个元素(位置点),判断其可以访问的所有位置,并将其加入到wait数组中,并将其flag置为1
  6. 计算小青从该位置到达每个可以访问的位置的距离,并记录最小值到dist数组中
  7. 当wait数组为空时,结束循环
  8. 重复步骤5-7,直到wait数组为空,或wait数组弹出元素为目的地K
  9. 取出dist数组中的最小值,即为小青从起始位置到目的地的最小距离

代码:

package main

import (
	"fmt"
	"math"
)

func main() {
	var N, K int
	fmt.Printf("请输入N K,以空格隔开\r\n")
	fmt.Scan(&N, &K)
	fmt.Println("最短时间为:", calculate(N, K), "分钟")
}

func calculate(N, K int) int {
	if N >= K {
		return N - K //只能掉头步行,直接返回n-k
	} else { 
		dist := make([]int, 100001)//每个点的距离
		for i := 0; i < 100001; i++ {
			dist[i] = math.MaxInt32
		}
		dist[N] = 0
		flag := make([]int, 100001) //标志 元素是否已计算
		flag[N] = 1
		wait := make([]int, 0) //等待计算的元素
		wait = append(wait, N)
		for len(wait) != 0 {
			num := wait[0] //取出队列首来计算
			wait = wait[1:] //队首弹出
			
			if num+1 < 100001 {
				if dist[num+1] > dist[num]+1 {
					dist[num+1] = dist[num] + 1
				}
				if flag[num+1] == 0 {
					wait = append(wait, num+1)
					flag[num+1] = 1
				}
			}
			if num-1 >= 0 {
				if dist[num-1] > dist[num]+1 {
					dist[num-1] = dist[num] + 1
				}
				if flag[num-1] == 0 {
					wait = append(wait, num-1)
					flag[num-1] = 1
				}
			}
			if num*2 < 100001 {
				if dist[num*2] > dist[num]+1 {
					dist[num*2] = dist[num] + 1
				}
				if flag[num*2] == 0 {
					wait = append(wait, num*2)
					flag[num*2] = 1
				}
			}
		}
		return dist[K]
	}
}