当青训营遇上码上掘金 主题 3:寻友之旅
我选择的主题描述如下:
主题 3:寻友之旅
小青要找小码去玩,他们的家在一条直线上,当前小青在地点 N ,小码在地点 K (0≤N , K≤100 000),并且小码在自己家原地不动等待小青。小青有两种交通方式可选:步行和公交。
步行:小青可以在一分钟内从任意节点 X 移动到节点 X-1 或 X+1
公交:小青可以在一分钟内从任意节点 X 移动到节点 2×X (公交不可以向后走)请帮助小青通知小码,小青最快到达时间是多久?
输入: 两个整数 N 和 K
输出: 小青到小码家所需的最短时间(以分钟为单位)
解题思路
求最快到达时间,由于小青每次移动的时间是固定的,因此最快到达的时间就相当于求解最少移动的次数。将坐标上所有整数视为节点,节点与节点之间如果可以通过步行或公交的方式直接到达,那么可以将这两个节点视为通过一条有向边直接相连。
如此一来,可以构造一个有向图,其中每个节点都对应一个非负整数。考虑到 0≤N , K≤100 000,因此节点的数量也是100 000。所有相邻的整数之间都有有向边相连,例如:1→2,2→3,3→2,2→1,以此类推。除此以外,每个整数还存在指向其2倍的整数节点的有向边,例如:2→4,4→8,3→6,以此类推。
如此建模之后,原题就转化成了在这个有向图上从地点N这个节点出发,最少经过几条有向边,才能到达地点K对应的节点。可以使用广度优先搜索算法(BFS)进行求解。
BFS算法
宽度优先搜索算法(又称广度优先搜索)是最简便的图的搜索算法之一,这一算法也是很多重要的图的算法的原型。Dijkstra单源最短路径算法和Prim最小生成树算法都采用了和宽度优先搜索类似的思想。其别名又叫BFS,属于一种盲目搜寻法,目的是系统地展开并检查图中的所有节点,以找寻结果。换句话说,它并不考虑结果的可能位置,彻底地搜索整张图,直到找到结果为止。
其算法过程如下:
- 访问顶点vi ;
- 访问vi 的所有未被访问的邻接点w1 ,w2 , …wk ;
- 依次从这些邻接点(在步骤②中访问的顶点)出发,访问它们的所有未被访问的邻接点; 依此类推,直到图中所有访问过的顶点的邻接点都被访问;
算法实现
通常可以使用一个先进先出(FIFO)的队列数据结构,来实现BFS算法。对于这一题,本文给出python代码实现的BFS代码,供读者参考,也可通过“码上掘金”平台查看:code.juejin.cn/api/raw/719…
# 广度优先搜索BFS即可,用队列实现
from queue import Queue
def main(N: int, K: int) -> int:
q = Queue()
q.put((N, 0))
while not q.empty():
cur = q.get()
if cur[0] == K:
return cur[1]
elif cur[0] < K:
if cur[0] <= 100000:
q.put((cur[0] + 1, cur[1] + 1)) # 往前走
q.put((cur[0] * 2, cur[1] + 1)) # 公交车
if cur[0] > 0:
q.put((cur[0] - 1, cur[1] + 1)) # 往回走
else: # cur[0] > K
q.put((cur[0] - 1, cur[1] + 1)) # 往回走
return 0
if __name__ == '__main__':
# n = int(input("请输入N:"))
# k = int(input("请输入K:"))
n = 1
k = 1023
res = main(n, k)
print('最短时间:', res)