广度优先搜索模型

BFS() {
1.建立起始步骤，队列初始化
2．遍历队列中的每一种可能，whlie(队列不为空)

}

出迷宫

• 代码
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
*/

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.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。

• 代码
/*
// Definition for Employee.
class Employee {
public int id;
public int importance;
public List<Integer> subordinates;
};
*/

class Solution {
public int getImportance(List<Employee> employees, int id) {
//将所有员工保存在map中
Map<Integer, Employee> map = new HashMap<>();
for (Employee em : employees) {
map.put(em.id, em);
}
//需要返回的重要性
int importance = 0;
//创建一个队列保存下属员工
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 叉树，返回其节点值的层序遍历。 (即从左到右，逐层遍历)。

[
[1],
[3,2,4],
[5,6]
]

• 代码
/*
// Definition for a Node.
class Node {
public int val;
public List<Node> children;

public Node() {}

public Node(int _val) {
val = _val;
}

public Node(int _val, List<Node> _children) {
val = _val;
children = _children;
}
};
*/

class Solution {
public List<List<Integer>> levelOrder(Node root) {

//创建一个队列保存每一层的节点数据
queue.offer(root);
List<List<Integer>> ret = new ArrayList<>();
if (root == null) return ret;
while (!queue.isEmpty()) {
//获取当前层的结点个数
int size = queue.size();
List<Integer> list = new ArrayList<>();
while (size-- > 0) {
//将该层所有结点的数据保存在链表中
Node cur = queue.poll();
//如果当前结点下一层还有结点就入队列
if (cur.children != null) {
for (Node node : cur.children) {
queue.offer(node);
}
}
}
}
return ret;
}
}


腐烂的橘子

• 题目描述
在给定的网格中，每个单元格可以有以下三个值之一：

• 代码
class Solution {

static class Node {
public int x;
public int y;

public Node(int x, int y) {
this.x = x;
this.y = y;
}
}

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

public int orangesRotting(int[][] grid) {

int row = grid.length;
if (row == 0) return 0;
int col = grid[0].length;

//需要一个队列保存坏的橘子
//遍历找到坏的橘子
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
if (grid[i][j] == 2) {
queue.offer(new Node(i, j));
}
}
}
int time = 0;
//如果此时有坏的橘子就进行处理感染
while (!queue.isEmpty()) {
//用一个数据判断是否进行了感染
boolean ok = false;
int size = queue.size();
//进行一分钟的感染
while (size-- > 0) {
Node cur = queue.poll();
//遍历该橘子的四周
for (int i = 0; i < 4; i++) {
int newR = cur.x + next[i][0];
int newC = cur.y + next[i][1];
//判断边界
if (newR < 0 || newR >= row || newC < 0 || newC >= col) {
continue;
}
//判断如果当前是新鲜橘子就进行感染
if (grid[newR][newC] == 1) {
grid[newR][newC] = 2;
ok = true;
//并将感染后的橘子放到队列中
queue.offer(new Node(newR, newC));
}
}
}
//如果有被感染
if (ok) {
time++;
}
}

//检查如果还有没被感染的橘子就返回-1
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
if (grid[i][j] == 1) {
return -1;
}
}
}

return time;
}
}


单词接龙

• 题目描述
给定两个单词（beginWord 和 endWord）和一个字典，找到从 beginWord 到 endWord 的最短转换序列的长度。转换需遵循如下规则：

• 代码
class Solution {
public int ladderLength(String beginWord, String endWord, List<String> wordList) {
//将所有单词放到hash表中 便于查询
Set<String> dict = new HashSet<>();
for (String word : wordList) {
}
//判断此时字典是否有这个endWord
if (!dict.contains(endWord)) {
return 0;
}
//使用一个set去保存访问过的单词
Set<String> used = new HashSet<>();
//使用一个队列去保存替换一次的单词
queue.offer(beginWord);
//计数器
int step = 1;

while (!queue.isEmpty()) {
//取出一次变化后的说有单词
int size = queue.size();
while (size-- > 0) {
String curWord = queue.poll();
//对这个单词进行每一个位置的每一个字符的替换
for (int i = 0; i < curWord.length(); i++) {
StringBuilder builder = new StringBuilder(curWord);
for (char ch = 'a'; ch <= 'z'; ch++) {
builder.setCharAt(i, ch);
String newWord = builder.toString();
//如果此时就是endWord就结束
if (newWord.equals(endWord)) {
return step + 1;
}
//判断这个新单词是否在字典中 没有被访问过
if (dict.contains(newWord) && !used.contains(newWord)) {
//否则入队列
queue.offer(newWord);
}
}
}
}
//完成所有size表示进行了一次改变
step++;
}
//如果到这还没有返回说明不能扎到
return 0;
}
}


打开转盘锁

• 题目描述
你有一个带有四个圆形拨轮的转盘锁。每个拨轮都有10个数字： ‘0’, ‘1’, ‘2’, ‘3’, ‘4’, ‘5’, ‘6’, ‘7’, ‘8’, ‘9’ 。每个拨轮可以自由旋转：例如把 ‘9’ 变为 ‘0’，‘0’ 变为 ‘9’ 。每次旋转都只能旋转一个拨轮的一位数字。

• 代码
class Solution {
public int openLock(String[] deadends, String target) {
for (String str : deadends) {
}
//如果0000是死亡数字那么永远有达不到
return -1;
}
//如果当前就是0000 就返回0
if (target.equals("0000")) {
return 0;
}
//用一个队列去保存此时的转盘上的数字
queue.offer("0000");
//计数器
int step = 0;
//用一个set保存访问过得密码
Set<String> used = new HashSet<>();

while (!queue.isEmpty()) {
int size = queue.size();
while (size-- > 0) {
String curStr = queue.poll();
//进行一次的拨盘
for (int i = 0; i < 4; i++) {
//一次波动有俩种可能
char newOne;
char newTwo;
//对curStr当前的字符是0/9要进行特殊处理
if (curStr.charAt(i) == '0' || curStr.charAt(i) == '9') {
if (curStr.charAt(i) == '0') {
newOne = '1';
newTwo = '9';
} else {
newOne = '0';
newTwo = '8';
}
} else {
newOne = (char) (curStr.charAt(i) + 1);
newTwo = (char) (curStr.charAt(i) - 1);
}
//将拨好的单个数字进行与其他三个字符想组合
StringBuilder oneBuilder = new StringBuilder(curStr);
StringBuilder twoBuilder = new StringBuilder(curStr);
oneBuilder.setCharAt(i, newOne);
twoBuilder.setCharAt(i, newTwo);
String oneStr = oneBuilder.toString();
String twoStr = twoBuilder.toString();
//对此时这俩个字符串进行判断
// 如果已经是target就返回操作步数
if (oneStr.equals(target) || twoStr.equals(target)) {
return step + 1;
}
//分别对俩个字符串进行判断是否为锁死密码和是否已经遍历过
queue.offer(oneStr);
}
queue.offer(twoStr);
}
}
}
step++;
}
return -1;
}
}

• 点赞 3
• 评论
• 分享
x

海报分享

扫一扫，分享海报

• 收藏 2
• 手机看

分享到微信朋友圈

x

扫一扫，手机阅读

• 打赏

打赏

Listen-Y

你的鼓励将是我创作的最大动力

C币 余额
2C币 4C币 6C币 10C币 20C币 50C币
• 一键三连

点赞Mark关注该博主, 随时了解TA的最新博文
04-20 169

04-27 491
07-03 104
10-09 1万+
09-24 1191
11-03 568
12-27 40