青训营 X 码上掘金

74 阅读1分钟

当青训营遇上码上掘金

主题 3:寻友之旅

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

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

算法思想:K为终点,N为起点,从N出发所到达的每一个点,我们可以把他叫做状态,如果说K点为最后一个状态,那么K点肯定是由它的前一个状态得来的,所以这个问题可以转化为:

  1. 如果起点N大于终点K,最短时间为N-K
    
  2. 如果K为奇数,那么它的上一个状态是K-1或者K+1
    
  3. 如果K为偶数,那么它的上一个状态为K/2,或者说最小的时间为K-N
    

代码如下:

func friend_seeking_trip(N, K int) int {
   if K <= N {
      return N - K
   }
   if K%2 == 0 {

      return int(math.Min(float64(1+friend_seeking_trip(N, K/2)), float64(K-N)))
   } else {
      return int(math.Min(float64(1+friend_seeking_trip(N, K-1)), float64(1+friend_seeking_trip(N, K+1))))
   }
}
  • 主题 4:攒青豆

    现有 n 个宽度为 1 的柱子,给出 n 个非负整数依次表示柱子的高度,排列后如下图所示,此时均匀从上空向下撒青豆,计算按此排列的柱子能接住多少青豆。(不考虑边角堆积)

攒青豆.png

算法思想:第一次遍历数组从左边开始,记录左边界小于等于右边界的区域大小;第二次遍历从右边开始,记录右边界小于等于左边界的区域大小;这里要注意,如果有两个相同的峰值情况下不要重复计算。

代码如下:

func green_soya_bean(height []int) int {
   res := 0
   temp := 0
   min := height[0]
   max := height[0]
   for i := 1; i < len(height); i++ {
      max = int(math.Max(float64(max), float64(height[i])))
      if height[i] >= min {
         res += temp
         temp = 0
         min = height[i]
      } else {
         temp += min - height[i]
      }
   }
   min = height[len(height)-1]
   temp = 0
   for i := len(height) - 2; i >= 0; i-- {

      if height[i] >= min {
         res += temp
         temp = 0
         min = height[i]
      } else {
         temp += min - height[i]
      }
      if height[i] == max {
         break
      }
   }
   return res
}