蓝桥杯—最少操作数
一.题目
分析:每次可以进行三次操作,求在n步操作后可以达到目标数的最小n,和最短路径问题相似,分层遍历加记忆化搜索防止时间复杂度过高,还需要减枝操作
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Set;
import java.util.Scanner;
public class Text10 {
public static int sum = 0;
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
long x = scan.nextLong();
int k = scan.nextInt();
Long n = x;
System.out.println(bfs(n,k));
scan.close();
}
public static int bfs(Long n,int k)
{
Queue<Long> queue = new LinkedList<>();
Set<Long> visted = new HashSet<>();//记录数组
queue.add(n);//存入初始值
Long res,tmp;
while(!queue.isEmpty())
{
int cnt = queue.size();
for(int i = 0;i<cnt;i++)//分层处理
{
res = queue.poll();
if(res==k)
return sum;
if(res>k)
{
queue.add(res - 1);
if(res-1==k) return sum + 1;
continue;
}
Long[] arr = {res + 1,res - 1,res * 2};
for(Long x:arr)
{
if(x==k) return sum + 1;
if(k>0&&!visted.contains(x))
{
queue.add(x);
visted.add(x);
}
}
}
sum++;//每一层sum+1
}
return -1;
}
}
二.总结
bfs算法求最短路径问题时,需要记忆化搜搜
原因
1.迷宫:防止后来的路径覆盖最短路径
2.本题:防止重复计算已经计算过的路径,减少时间复杂度
本题需要大量减枝,因为每次操作变化小,这也是为什么不能用dfs的原因,dfs算法也可以求解,不过时间复杂度很高,递归太深入了,比如说1到10000会进行9999次递归,时间复杂度是指数级的
3.只有答案需要返回操作步骤数时才需要分层处理,比如求最短路径就不需要分层处理,只需要返回路径就可以,如果是需要知道走了几步,那就需要分层处理记录
三.错误总结
1.时间复杂度过高
没有减枝,当当前数大于k时,只需要-1操作就行,没有设置记忆数组,已经遍历过的结果不需要再次遍历,使用Hashset是因为它是哈希表结构,查询快效率高
2.没有思考清楚什么情况会返回-1
没有返回-1的情况,题目陷阱
3.返回值错误
eg:
在这里如果没有检查res就可能会发生错误
假如说在第n层res-1的结果等于k,那么res-1就存储在第85层,如果在这个位置前有一个值+1可以等于k那么返回来sum+1在86层,就导致结果错误,所以每次操作都需要立即检查,没检查就会导致多一层搜索