当青训营遇上码上掘金之“寻友之旅”
题目
小青要找小码去玩,他们的家在一条直线上,当前小青在地点 N ,小码在地点 K (0≤N , K≤100 000),并且小码在自己家原地不动等待小青。小青有两种交通方式可选:步行和公交。
步行:小青可以在一分钟内从任意节点 X 移动到节点 X-1 或 X+1
公交:小青可以在一分钟内从任意节点 X 移动到节点 2×X (公交不可以向后走)
请帮助小青通知小码,小青最快到达时间是多久?
输入: 两个整数 N 和 K
输出: 小青到小码家所需的最短时间(以分钟为单位)
解题思路
- 我们通过题目可以发现N的值是不会变为负数的,因为变为负数之后,我们只有进行
N=N+1操作才能再次变为正数,这样就导致花费的时间变长 - 如果在
N>K的情况下,我们只需要通过-1操作就能得到结果;如果是N<K的情况,我们可以通过三种方式组合的方法来得到结果 - 小青是一定可以到达小码所在位置的,也就是说该题目一定是有解的,因为最坏的情况下我们可以通过
+1或者-1得到结果 - 由于该题目是求最短时间,所以考虑使用BFS算法实现。通过visit数组来判断一个结点是否已经走过。用Node类来存放路径的值以及花费的时间,使用带参构造函数来加入结点。需要注意的是在加入新的结点的时候,要判断该结点是否走过
- 每次移动共有三种状态,三种状态的操作值都是1,按三种操作层次搜索,当优先搜索到目标值,直接返回结果即可,BFS搜索每次都是优先最短距离进行搜索
代码实现
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
public class Main {
static int k;
static int[] visit = new int[1000000];
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
//输入当前位置
int n = sc.nextInt();
//输入目标位置
k = sc.nextInt();
sc.close();
System.out.println(BFS(n));
}
public static int BFS(int n) {
Node next;
Node head = new Node(n,0);
Queue<Node> queue = new LinkedList<>();
//把head元素插入队列
queue.offer(head);
//在visit数组中把走过的元素设置为1
visit[head.x]=1;
//当队列不为空时进行循环,如果队列为空则停止循环
while(!queue.isEmpty()) {
//取出队列第一个元素赋值给next
next=queue.poll();
//num表示当前位置
int num=next.x;
//若当前位置等于目标位置,返回需要的步数
if(num== k) {
return next.step;
}
else {
//若当前位置不等于目标位置
//遍历当前位置的结点
int a=num+1,b=num-1,c=num*2;
if(a>=0 && a<=100000 && visit[a]==0) {
//把当前结点插入队列
queue.offer(new Node(a,next.step+1));
//在数组中把当前位置的元素设置为1
visit[a]=1;
}
if(b>=0 && b<=100000 && visit[b]==0) {
queue.offer(new Node(b,next.step+1));
visit[b]=1;
}
if(c>=0 && c<=100000 && visit[c]==0) {
queue.offer(new Node(c,next.step+1));
visit[c]=1;
}
}
}
return 0;
}
}
class Node{
/**
* 小青当前的位置
*/
int x;
/**
* 小青到达x所需的步数
*/
int step;
Node(int x,int step){
this.x=x;
this.step=step;
}
}
个人总结
希望青训营能充实我的寒假生活,提升我的专业技术水平,一起加油吧!