搜索:
BFS:广度优先
每一层遍历的节点都与根节点距离相同。设 di 表示第 i 个节点与根节点的距离,推导出一个结论:对于先遍历的节点 i 与后遍历的节点 j,有 di <= dj。利用这个结论,可以求解最短路径等 最优解 问题:第一次遍历到目的节点,其所经过的路径为最短路径。应该注意的是,使用 BFS 只能求解无权图的最短路径。
在程序实现 BFS 时需要考虑以下问题:
- 队列:用来存储每一轮遍历得到的节点;
- 标记:对于遍历过的节点,应该将它标记,防止重复遍历。
1) 每一层遍历的节点都与根节点距离相同:决定了什么时候path++:就是每遍历一层之前保留queue.size,这个size就是这一层的大小
2) 什么时候置flag?已经从队列中poll了之后
3) 最优解问题:因为每次遍历的都是和根节点距离相同的节点,所以最先到达终点的一定是最短路径
1091. 二进制矩阵中的最短路径(m)(经典BFS+visited)
重点:注意只有{0}一个数的情况
public int shortestPathBinaryMatrix(int[][] grid) {
if(grid[0][0]==1 || grid[grid.length-1][grid[0].length-1]==1)
return -1;
if (grid.length == 1 && grid[0][0] == 0) {
return 1;
}
// 顺时针
int[][] xOy = {
{-1,0},{-1,-1},{0,-1},{1,-1},{1,0},{1,1},{0,1},{-1,1}};
// int[][] xOy = {
{1, 0}, {1, 1}, {1,-1}, {0, 1}, {0, -1}, {-1, 0},{-1, -1}, {-1, 1}};
int n = grid.length;
boolean[][] visited = new boolean[n][n];
visited[0][0] = true;
Queue<int[]> queue = new LinkedList<>();
queue.add(new int[] {0,0});
int pathLength = 0;
while (!queue.isEmpty()) {
// 这一层节点的个数
int size = queue.size();
pathLength++;
while (size-- > 0) {
int[] node = queue.poll();
int x = node[0];
int y = node[1];
// grid[x][y] = 1;
for (int[] d : xOy) {
int nx = x + d[0];
int ny = y + d[1];
if (nx == n-1 && ny == n-1) {
return pathLength+1;
}
if (nx < 0 || nx >= n || ny < 0 || ny >= n || visited[nx][ny] || grid[nx][ny] == 1){
continue;
}
visited[nx][ny] = true;
queue.add(new int[] {nx,ny});
}
}
}
return -1;
}
279. 完全平方数(m)
思路:
可以将每个整数看成图中的一个节点,如果两个整数之差为一个平方数,那么这两个整数所在的节点就有一条边。
要求解最小的平方数数量,就是求解从节点 n 到节点 0 的最短路径。
本题也可以用动态规划求解,在之后动态规划部分中会再次出现。
完全平方数的规律:1,4,9,16.。。中间刚好相差(3,5,7,9....),即n^2-(n-1)^2 = 2n-1
public int numSquares(int n) {
List<Integer> list = generateSquares(n);
Queue<Integer> queue = new LinkedList<>();
boolean[] visited = new boolean[n+1];
queue.add(n);
visited[n] = true;
int level = 0;
while (!queue.isEmpty()) {
int size = queue.size();
level++;
while (size-- > 0) {
int cur = queue.poll();
for (int i: list
) {
int next = cur - i;
// 因为LinkedList是按顺序读,我们存的时候就是(1,4,9...)
if (next < 0) {
break;
}
if (next == 0) {
return level;
}
visited[next] = true;
queue.add(next);
}
}
}
return n;
}
/**
* 生成小于 n 的平方数序列
* @return 1,4,9,...
*/
private List<Integer> generateSquares(int n) {
List<Integer> squares = new ArrayList<>();
int square = 1;
int diff = 3;
while (square <= n) {
squares.add(square);
square += diff;
diff += 2;
}
return squares;
}
127. 单词接龙(m)(重点!&#x