当青训营遇上码上掘金
题目描述
小青要找小码去玩,他们的家在一条直线上,当前小青在地点 N ,小码在地点 K (0≤N , K≤100000),并且小码在自己家原地不动等待小青。小青有两种交通方式可选:步行和公交。
步行:小青可以在一分钟内从任意节点 X 移动到节点 X-1 或 X+1
公交:小青可以在一分钟内从任意节点 X 移动到节点 2×X (公交不可以向后走)
请帮助小青通知小码,小青最快到达时间是多久?
输入: 两个整数 N 和 K
输出: 小青到小码家所需的最短时间(以分钟为单位)
思路
BFS,从小青在的地点,开始搜索小青可以到达的所有节点,直到找到小码。
小青所在点是N,从N节点开始进行广搜,把可达未入队地点入队,然后拿队头节点搜(有三个,分别是+1 -1 *2)如果能更新结果dist数组就更新,不能更新就出队,继续一层一层的找下去。dist 记录答案,dist[i] 代表从节点N 到达节点i 所需的最短时间。 如果已经找到了小青,那么就直接返回dist【i】就可以了。
广搜的结果就是最短路径。
代码实现
go菜鸡想找实现好的队列,但是很遗憾没找到。go好像没有实现好的队列,所以自己手写了一个队列。
package main
import (
"fmt"
)
type Queue struct {
List []int
}
// 创建一个新队列
func newQueue() *Queue {
list := make([]int, 0)
return &Queue{List: list}
}
// 入队一个数据
func (q *Queue) inQ(data int) {
q.List = append(q.List, data)
}
// 出队一个数据
func (q *Queue) popQ() int {
if len(q.List) == 0 {
return -1
}
data := q.List[0]
q.List = append(q.List[1:])
return data
}
// 判断队列是否为空
func (q *Queue) empty() bool {
if len(q.List) == 0 {
return true
}
return false
}
func bfs(n int, k int) int {
//小青和小码在同一个位置
if n == k {
return 0
}
//结果数组,存结果
var dist [100000]int
for count := 0; count < len(dist); count++ {
dist[count] = 100005
}
//是否访问过数组,防止重复入队
var vis [100000]bool
//队列
queue := newQueue()
//小青位置n入队了
queue.inQ(n)
dist[n] = 0
vis[n] = true
for !queue.empty() {
currentNode := queue.popQ()
//找到小青所在地k了
if currentNode-1 == k || currentNode+1 == k || currentNode*2 == k {
return dist[currentNode] + 1
}
// 步行向后走一步
if currentNode > 0 && dist[currentNode-1] > dist[currentNode]+1 {
dist[currentNode-1] = dist[currentNode] + 1
if !vis[currentNode-1] {
queue.inQ(currentNode - 1)
vis[currentNode-1] = true
}
}
// 步行向前走一步
if currentNode < 100000 && dist[currentNode+1] > dist[currentNode]+1 {
dist[currentNode+1] = dist[currentNode] + 1
if !vis[currentNode+1] {
queue.inQ(currentNode + 1)
vis[currentNode+1] = true
}
}
// 公交
if 2*currentNode <= 100000 && dist[2*currentNode] > dist[currentNode]+1 {
dist[2*currentNode] = dist[currentNode] + 1
if !vis[2*currentNode] {
queue.inQ(2 * currentNode)
vis[2*currentNode] = true
}
}
}
return -1
}
func main() {
fmt.Println(bfs(2, 4096))
}