@
目录
- 一、知识及框架
- 二、案例说明
- 案例1:使用bfs计算二叉树的最小高度
- 案例2:解开密码锁的最少次数,要求:请写一个算法,初始状态为0000,拨出target的最少次数,其中避免出现deadends中的包含的任意一个死亡密码,如果永远无法拨出target,则返回-1
- 本人其他文章链接
一、知识及框架
- BFS算法都是用 “队列” 结构
- BFS和DFS最主要区别:bfs找到的路径一定是最短的,但代价是空间复杂度比dfs大很多
- bfs本质:一幅图,从起点到终点,求最短路径
- bfs空间复杂度高,而dfs空间复杂度较低
- 形象点说:dfs是线,bfs是面,dfs是单打独斗,bfs是集体行动
- dfs和bfs的时间复杂度都是O(N)
- BFS干的事:从起点start到终点target的最近距离
- BFS应用举例:走迷宫、连连看......
※ 思考问题1:为什么bfs、dfs都可以找到最短距离,但一般都使用bfs方法,而不用dfs呢?
答:bfs是齐头并进,一旦找到终点就不找了,而dfs需要全遍历后才知道最短路径
※ 思考问题2:既然bfs那么好,为啥dfs还需要存在?
答:bfs代价太大,除找最短路径用bfs,其他情况推荐dfs
BFS框架:
二、案例说明
说明:Node节点class对象代码请查看上一篇文章,https://blog.csdn.net/a924382407/article/details/118394577
二叉树
/* a1:↓ a2:↓ a3:↓1 1 1/ \ / \2 3 2 3/ \4 5/6*/Node a1 = new Node(1, new Node(2, new Node(4), new Node(5, new Node(6), null)), new Node(3));Node a2 = new Node(1, null, null);Node a3 = new Node(1, new Node(2, null, null), new Node(3, null, null));
main函数
public static void main(String[] args){//问题3.1:使用bfs计算二叉树的最小高度System.out.println("使用bfs计算二叉树的最小高度:" + bfsMinDepth(a1));//问题3.2:解开密码锁的最少次数System.out.println("解开密码锁的最少次数:" + openLock(new String[]{"8887", "7789"}, "8888"));
}
案例1:使用bfs计算二叉树的最小高度
//问题3.1:使用bfs计算二叉树的最小高度public static int bfsMinDepth(Node root) {if (root == null) return 0;Queue<Node> q = new LinkedList<>();q.offer(root);//root本身就是一层,将depth初始化为1int depth = 1;while (!q.isEmpty()) {int sz = q.size();//将当前队列中所有节点想四周扩散for (int i = 0; i < sz; i++) {Node cur = q.poll();//判断是否到达终点if (cur.left == null && cur.right == null) return depth;//将cur的相邻节点加入队列if (cur.left != null) q.offer(cur.left);if (cur.right != null) q.offer(cur.right);}//重点:这里增加步数depth++;}return depth;}
案例2:解开密码锁的最少次数,要求:请写一个算法,初始状态为0000,拨出target的最少次数,其中避免出现deadends中的包含的任意一个死亡密码,如果永远无法拨出target,则返回-1
/*** 问题3.2:解开密码锁的最少次数* 要求:请写一个算法,初始状态为0000,拨出target的最少次数,其中避免出现deadends中的包含的任意一个死亡密码,如果永远无法拨出target,则返回-1*///将s[j]向上拨动一次public static String plusOne(String s, int j) {char[] ch = s.toCharArray();if (ch[j] == '9') {ch[j] = '0';} else {ch[j] += 1;}return new String(ch);}//将s[j]向下拨动一次public static String minusOne(String s, int j) {char[] ch = s.toCharArray();if (ch[j] == '0') {ch[j] = '9';} else {ch[j] -= 1;}return new String(ch);}/*** openLock* @param deadends 死亡数字* @param target 目标密码* @return 次数*/public static int openLock(String[] deadends, String target) {//记录需要跳过的死亡密码Set<String> deads = new HashSet<>();for (String s : deadends) deads.add(s);//记录已经穷举过的密码,防止走回头路Set<String> visited = new HashSet<>();Queue<String> q = new LinkedList<>();//从起点开始启动广度搜先搜索int step = 0;q.offer("0000");visited.add("0000");while (!q.isEmpty()) {int sz = q.size();//将当前队列中所有节点向四周扩散for (int i = 0; i < sz; i++) {String cur = q.poll();//判断密码是否合法,是否到达终点if (deads.contains(cur)) continue;if (cur.equals(target)) return step;//将一个节点的未遍历相邻节点加入队列for (int j = 0; j < 4; j++) {String up = plusOne(cur, j);if (!visited.contains(up)) {q.offer(up);visited.add(up);}String down = minusOne(cur, j);if (!visited.contains(down)) {q.offer(down);visited.add(down);}}}//重点:增加步数step++;}//如果穷举完都没找到目标密码,那就是找不到了return -1;}
本人其他文章链接
1.单链表题+数组题(快慢指针和左右指针)
2.BFS(Breath First Search 广度优先搜索)
3.”回溯算法“框架及练习题
4.JAVA 二叉树面试题