算法~广度优先搜索(Breadth First Search)一石激起干层浪(附带6道练习题)

  • 打开转盘锁

广度优先搜索模型


BFS() {

1.建立起始步骤,队列初始化

2.遍历队列中的每一种可能,whlie(队列不为空)

通过队头元素带出下一步的所有可能,并且依次入队

判断当前情况是否达成目标:按照目标要求处理逻辑

继续遍历队列中的剩余情况

}

出迷宫

假设有一个迷宫,里面有障碍物,迷宫用二维矩阵表示,标记为O的地方表示可以通过,标记为1的地方表示障碍物,不能通过。现在给一个迷宫出口,让你判断是否可以从入口进来之后,走出迷宫,每次可以向任意方向走。

假设是一个10*10的迷宫,入口在(1,1)的位置,出口在(8,10)的位置,通过(1,1)一步可以走到的位置有两个(1,2),(2,1)·但是这两个点并不是出口,需要继续通过这两个位置进一步搜索,假设现在在(1,2),下一次一步可以到达的新的位置为(1,3),(2.2)。而通过(2,1)可以一步到达的新的位置为(2,2),(3,1),但是这里(2,2)是重复的,所以每一个点在走的过程中需要标记是否已经走过了。

两步之后,还没没有走到出口,这时候需要通过新加入的点再去探索下一步能走到哪些新的点上,重复这个过程,直到走到出口为止。

  • 代码

import java.util.LinkedList;

import java.util.Queue;

import java.util.Scanner;

/**

  • Created with IntelliJ IDEA.

  • Description: If you don’t work hard, you will a loser.

  • User: Listen-Y.

  • Date: 2020-09-22

  • Time: 21:34

*/

public class SolutionBreadth {

static class Node {

public int x;

public int y;

public Node(int x, int y) {

this.x = x;

this.y = y;

}

}

/**

  • 迷宫问题

*/

public static void main(String[] args) {

int sr, sc, endR, endC;

Scanner scanner = new Scanner(System.in);

System.out.print(“输入迷宫起点与终点:”);

sr = scanner.nextByte();

sc = scanner.nextByte();

endR = scanner.nextByte();

endC = scanner.nextByte();

int[][] gird = {{0,1,0,0},

{0,0,0,1},

{0,1,0,0},

{0,0,1,0}};

System.out.println(DFS(gird, sr, sc, endR, endC));

}

private static int[][] next = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};

private static boolean DFS(int[][] gird, int sr, int sc, int endR, int endC) {

int row = gird.length;

if (row == 0) {

return false;

}

int col = gird[0].length;

//需要一个used保存访问过得点

boolean[][] used = new boolean[row][col];

//需要一个队列保存需要遍历的点

Queue queue = new LinkedList<>();

queue.offer(new Node(sr, sc));

//标记起点已被使用

used[sr][sc] = true;

//只要队列不为空就说明还有机会到达终点

while (!queue.isEmpty()) {

//查看起点的四周, 看哪个方向可以走

for (int i = 0; i < 4; i++) {

int newX = queue.peek().x + next[i][0];

int newY = queue.peek().y + next[i][1];

//判断边界

if (newX < 0 || newX >= row || newY < 0 || newY >= col) {

continue;

}

//如果此时位置无障碍, 并且未被访问就入队列

if (gird[newX][newY] == 0 && !used[newX][newY]) {

queue.offer(new Node(newX, newY));

//并标记这点被访问过

used[newX][newY] = true;

}

//如果此时已经是终点就结束方法

if (newX == endR && newY == endC) {

return true;

}

}

//否则就出队列判断下一个点

queue.poll();

}

return false;

}

}

员工的重要性

  • 题目描述

给定一个保存员工信息的数据结构,它包含了员工唯一的id,重要度 和 直系下属的id。

比如,员工1是员工2的领导,员工2是员工3的领导。他们相应的重要度为15, 10, 5。那么员工1的数据结构是[1, 15, [2]],员工2的数据结构是[2, 10, [3]],员工3的数据结构是[3, 5, []]。注意虽然员工3也是员工1的一个下属,但是由于并不是直系下属,因此没有体现在员工1的数据结构中。

现在输入一个公司的所有员工信息,以及单个员工id,返回这个员工和他所有下属的重要度之和。

示例 1:

输入: [[1, 5, [2, 3]], [2, 3, []], [3, 3, []]], 1

输出: 11

解释:

员工1自身的重要度是5,他有两个直系下属2和3,而且2和3的重要度均为3。因此员工1的总重要度是 5 + 3 + 3 = 11。

来源:力扣(LeetCode)

链接:https://leetcode-cn.com/problems/employee-importance

著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

  • 代码

/*

// Definition for Employee.

class Employee {

public int id;

public int importance;

public List subordinates;

};

*/

class Solution {

public int getImportance(List employees, int id) {

//将所有员工保存在map中

Map<Integer, Employee> map = new HashMap<>();

for (Employee em : employees) {

map.put(em.id, em);

}

//需要返回的重要性

int importance = 0;

//创建一个队列保存下属员工

Queue queue = new LinkedList<>();

queue.offer(map.get(id));

while (!queue.isEmpty()) {

//获得当前有队列里有几个下属员工

int size = queue.size();

while (size-- > 0) {

//获取下属

Employee employ = queue.poll();

importance += employ.importance;

//判断当前员工还有没有下属 如果有就加到队列中

if (employ.subordinates != null) {

for (int curId : employ.subordinates) {

queue.offer(map.get(curId));

}

}

}

}

return importance;

}

}

N叉树的遍历

  • 题目描述

给定一个 N 叉树,返回其节点值的层序遍历。 (即从左到右,逐层遍历)。

例如,给定一个 3叉树 :

在这里插入图片描述

返回其层序遍历:

[

[1],

[3,2,4],

[5,6]

]

来源:力扣(LeetCode)

链接:https://leetcode-cn.com/problems/n-ary-tree-level-order-traversal

著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

  • 代码

/*

// Definition for a Node.

class Node {

public int val;

public List children;

public Node() {}

public Node(int _val) {

val = _val;

}

public Node(int _val, List _children) {

val = _val;

children = _children;

}

};

*/

class Solution {

public List<List> levelOrder(Node root) {

//创建一个队列保存每一层的节点数据

Queue queue = new LinkedList<>();

queue.offer(root);

List<List> ret = new ArrayList<>();

if (root == null) return ret;

while (!queue.isEmpty()) {

//获取当前层的结点个数

int size = queue.size();

List list = new ArrayList<>();

while (size-- > 0) {

//将该层所有结点的数据保存在链表中

Node cur = queue.poll();

list.add(cur.val);

//如果当前结点下一层还有结点就入队列

if (cur.children != null) {

for (Node node : cur.children) {

queue.offer(node);

}

}

}

ret.add(list);

}

return ret;

}

}

腐烂的橘子

  • 题目描述

在给定的网格中,每个单元格可以有以下三个值之一:

值 0 代表空单元格;

值 1 代表新鲜橘子;

值 2 代表腐烂的橘子。

每分钟,任何与腐烂的橘子(在 4 个正方向上)相邻的新鲜橘子都会腐烂。

返回直到单元格中没有新鲜橘子为止所必须经过的最小分钟数。如果不可能,返回 -1。
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

img

最近我根据上述的技术体系图搜集了几十套腾讯、头条、阿里、美团等公司21年的面试题,把技术点整理成了视频(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,这里以图片的形式给大家展示一部分

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!**

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

img

[外链图片转存中…(img-xLROM9iP-1712980252805)]

最近我根据上述的技术体系图搜集了几十套腾讯、头条、阿里、美团等公司21年的面试题,把技术点整理成了视频(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,这里以图片的形式给大家展示一部分

[外链图片转存中…(img-8ZFVqsNt-1712980252805)]

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

  • 13
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值