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

57 阅读1分钟

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

  • 解题思路分析:
  • 小青可移动,每次移动可以向前(步行向前一步或者坐车2步)或者向后

寻友之旅.png

  • 当N>=K时,最短时间是N-k,此时只能往后走
  • 当N<K时,此时可以步走或者乘车
  • 采用BFS方式,用distance保存小青到当前节点的最短时间
  • flag表示当前节点是否被访问过
  • wait保存当前小青可以去到的位置
  • 算法实现:
  • distacne 数组保存小青到当前位置的最短时间
  • flag 数组表示当前位置是否已经处理过
  • wait 数组表示小青可以走到的位置
  • 初始化阶段:distance 用math.MaxInt32c初始化,根据100001确定
  • distance[初始位置]=0
  • flag[初始位置] = ture
  • wait = append(当前位置加入)
  • for wait数组中没有元素{
  • 获取当前位置
    
  • 将当前位置剔除
    
  • 判断当前位置+1是否越界{
    
  •     if 比较当前位置 往前走一步 < 下一个可达到位置distance[当前位置+1]{
    
  •     修改distance[当前位置+1],保证distane保存的值是最小的
    
  •     }
    
  • }
    
  • 判断当前位置-1是否越界{
    
  •     if 比较当前位置 往后走一步 < 下一个可达到位置distance[当前位置-1]{
    
  •     修改distance[当前位置-1],保证distane保存的值是最小的
    
  •     }
    
  • }
    
  • 判断当前位置+1是否越界{
    
  •     if 比较当前位置 往前走2步 < 下一个可达到位置distance[当前位置+1]{
    
  •     修改distance[当前位置*2],保证distane保存的值是最小的
    
  •     }
    
  •     distance[K]//表示小青从N出发到达的K的最短距离/1
    
  • }
    
  • }
package main

import (
   "fmt"
   "math"
)

// 输入两个点的位置,返回到达的最小实际按
func minSecond(n, k int) int {
   if n >= k {
      // 表示只能步行往后走
      return n - k
   } else {
      // 往前走可以步行或者坐公交车

      //distance保存小青到当前节点的最短时间
      distance := make([]int, 100001)
      for i := 0; i < 100001; i++ {
         //100001 在2^32之内
         distance[i] = math.MaxInt32
      }
      distance[n] = 0

      //flag标志当前节点是否访问过
      flag := make([]bool, 100001)
      flag[n] = true
      // 保存小青可以到达的位置
      wait := make([]int, 0)
      wait = append(wait, n)
      for len(wait) != 0 {
         num := wait[0]
         wait = wait[1:]

         // 小青往前走,当前位置走一步 小于下一个位置保存的值
         if num+1 < 100001 {
            if distance[num+1] > distance[num]+1 {
               distance[num+1] = distance[num] + 1
            }
            if !flag[num+1] {
               wait = append(wait, num+1)
               flag[num+1] = true
            }
         }
         //往后走一步,当前位置 + 1小于 下一个节点值
         if num-1 >= 0 {
            if distance[num-1] > distance[num]+1 {
               distance[num-1] = distance[num] + 1
            }
            if !flag[num-1] {
               wait = append(wait, num-1)
               flag[num-1] = true
            }
         }
         // 走两步
         if num*2 < 100001 {
            if distance[num*2] > distance[num]+1 {
               distance[num*2] = distance[num] + 1
            }
            if !flag[num*2] {
               wait = append(wait, num*2)
               flag[num*2] = true
            }
         }
      }
      return distance[k]
   }

}
func main() {
   var K, N int
   fmt.Println("请输入两个数字K,N")
   fmt.Scanf("%d %d", &K, &N)
   fmt.Println("达到最短时间为", minSecond(N, K), "分钟")
}