当青训营遇上码上掘金

174 阅读2分钟

当青训营遇上码上掘金

主题3、寻友之旅

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

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

1、思路

如果N>KN > K,小青只能步行从N走道K,最短时间为NKN - K

如果N=KN = K,小青无需移动就能见到小码,最短时间为0;

如果N<KN < K,小青可以选择坐公交和步行前往,NNKK的范围不大,这部分可以用bfs来求最短时间。

2、解题方法

用dis数组来记录NN到位置XX的最短时间,初始化dis数组的所有值为INFINF,使用堆优化来获取队列中离起点最近的点,如果他到向前、向后、乘2三个点的距离比当前dis数组中的值更小,则更新dis数组中起点到该点的距离,并将其加入队列中,如果到达终点KK则搜索结束,dis[k]即为从NNKK的最短时间。

3、代码

主题4、攒青豆

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

攒青豆.png

1、思路

一个格子能存青豆的前提条件是左右都有高度大等于当前格子高度的柱子,最大水位的高度取决于较矮柱子的高度,我们可以用maxleftmaxleftmaxrightmaxright来记录左右两边已知的最大高度,随着leftleftrightright两个指针的移动,最大高度会进行更新。

2、解题方法

维护两个指针leftleftrightright和两边最大存青豆高度maxleftmaxleftmaxrightmaxright,初始化leftleft为2,rightrightn2n - 2maxleftmaxleftmaxrightmaxright为0。

  • height[left1]<height[right+1]height[left - 1] < height[right + 1]时,更新maxleftmaxleft,此时maxleft<maxrightmaxleft < maxright,left处能接到的青豆为max(maxleftheight[left],0)max(maxleft - height[left], 0),将结果记录后left+1left + 1
  • height[left1]>=height[right+1]height[left - 1] >= height[right + 1]时,更新maxrightmaxright,此时maxleft>=maxrightmaxleft >= maxright,right处能接到的青豆为max(maxrightheight[right],0)max(maxright - height[right], 0),将结果记录后right1right - 1。 结果即为能接到的青豆数量。

3、代码