BFS
何时应用BFS
图的遍历
层级遍历 ---- level order traversal
由点及面 ---- clone graph, number of islands
拓扑排序 --- alien dictionary
简单图最短路径
word ladder
clone graph
word ladder
number of islands
Clone Graph
实际写的时候思路还是不够清晰,基本功需要多练
BFS遍历每个Cur的neighbors
同时用一个Map来存node和CloneNode
对每个Cur.neighbor看是否在map里,如果在了就说明已经遍历过,不需要放到queue里
如果不在的话就需要新建一个cloneNeighbor并放到map里
最后把cloneNeighbor加入到cloneCur的neighbors
public Node cloneGraph(Node node) {
if (node == null) return null;
Queue<Node> nodes = new LinkedList<>();
nodes.add(node);
Map<Node, Node> map = new HashMap<>(); //key is node, val is cloneNode
map.put(node, new Node(node.val, new ArrayList<Node>()));
while (!nodes.isEmpty()) {
Node cur = nodes.poll();
for (Node neighbor : cur.neighbors) {
if (!map.containsKey(neighbor)) {
//add neighbor into map
map.put(neighbor, new Node(neighbor.val, new ArrayList<Node>()));
nodes.offer(neighbor);
}
//add cloneNeighbor into cloneCur
map.get(cur).neighbors.add(map.get(neighbor));
}
}
return map.get(node);
}
DFS 解法
class Solution {
public Node cloneGraph(Node node) {
if (node == null) return null;
Map<Node, Node> map = new HashMap<>();
return cloneNode(node, map);
}
private Node cloneNode(Node node, Map<Node, Node> map) {
if (map.containsKey(node)) {
return map.get(node);
}
Node cloneNode = new Node(node.val, new ArrayList<Node>());
map.put(node, cloneNode);
for (Node neighbor : node.neighbors) {
Node cloneNeighbor = cloneNode(neighbor, map);
map.put(neighbor, cloneNeighbor);
cloneNode.neighbors.add(cloneNeighbor);
}
return cloneNode;
}
}
Word Ladder
先想简单的BFS解法,寻找隐式图最短路径
optimize: Bi-BFS
class Solution {
public int ladderLength(String beginWord, String endWord, List<String> wordList) {
HashSet<String> visited = new HashSet<>();
HashSet<String> dict = new HashSet<>();
for(int i = 0; i< wordList.size(); i++){
dict.add(wordList.get(i));
}
if (!dict.contains(endWord)) return 0;
Queue<String> q = new LinkedList<>();
q.add(beginWord); //assume beginWord and endWord are not the same.
visited.add(beginWord);
int level =1;
while(!q.isEmpty()){
level++;
int size = q.size();
for(int j=0; j< size; j++){
String str = q.poll();
for(int k = 0; k<str.length();k++){
char [] chars = str.toCharArray();
for(char c = 'a'; c <= 'z'; c++){
chars [k] = c;
String word = new String(chars);
if(word.equals(endWord)&& dict.contains(word)){
return level;
}
if(dict.contains(word) && !visited.contains(word)){
q.add(word);
visited.add(word);
}
}
}
}
}
return 0;
}
}
Number of island
矩阵类BFS的基础题,由点及面BFS
构建deltaX[ ] = {-1, 0, 0, 1}, deltaY = {0, -1, 1, 0}
BFS Queue存什么?可以是tuple{x, y}, 也可以是val = x * cols + y。 x = val / cols, y = val % cols
还可以DFS, union find解
BFS解法
class Solution {
public int numIslands(char[][] grid) {
if (grid == null || grid.length == 0 || grid[0].length == 0) {
return 0;
}
//坐标变换数组
//x = [-1, 0 , 0 , 1]
//y = [0, 1, -1, 0]
int rows = grid.length;
int cols = grid[0].length;
int[][] visited = new int[rows][cols];
int num = 0;
for (int row = 0; row < rows; row++) {
for (int col = 0; col < cols; col++) {
if (grid[row][col] == '1' && visited[row][col] == 0) {
bfs(grid, row, col, visited);
num++;
}
}
}
return num;
}
private void bfs(char[][] grid, int row, int col, int[][] visited) {
//what to store into a queue? either a tuple object or x * rows + y
Queue<Integer> queue = new LinkedList<>();
int rows = grid.length;
int cols = grid[0].length;
queue.offer(row * cols + col);
visited[row][col] = 1;
int[] deltaX = {-1, 0 , 0 , 1};
int[] deltaY = {0, 1, -1, 0};
while (!queue.isEmpty()) {
int cur = queue.poll();
int x = cur / cols;
int y = cur % cols;
for (int i = 0; i < 4; i++) {
int nextX = x + deltaX[i];
int nextY = y + deltaY[i];
if (isValid(grid, nextX, nextY, visited)) {
queue.offer(nextX * cols + nextY);
visited[nextX][nextY] = 1;
}
}
}
}
private boolean isValid(char[][] grid, int row, int col, int[][] visited) {
int rows = grid.length;
int cols = grid[0].length;
return 0 <= row && row < rows && 0<= col && col < cols && grid[row][col] == '1'&& visited[row][col] != 1;
}
}
DFS解法
class Solution {
public int numIslands(char[][] grid) {
if (grid == null || grid.length == 0 || grid[0].length == 0) return 0;
int rows = grid.length;
int cols = grid[0].length;
int[][] visited = new int[rows][cols];
int num = 0;
for (int row = 0; row < rows; row++) {
for(int col = 0; col < cols; col++) {
if (grid[row][col] == '1' && visited[row][col] == 0) {
dfs(grid, row, col, visited);
num++;
}
}
}
return num;
}
private void dfs(char[][] grid, int x, int y, int[][] visited) {
if (isValid(grid, x, y, visited)) {
visited[x][y] = 1;
dfs(grid, x - 1, y, visited);
dfs(grid, x + 1, y, visited);
dfs(grid, x, y - 1, visited);
dfs(grid, x, y + 1, visited);
}
}
private boolean isValid(char[][] grid, int x, int y, int[][] visited) {
int rows = grid.length;
int cols = grid[0].length;
return 0 <= x && x < rows && 0<= y && y < cols && grid[x][y] == '1' && visited[x][y] == 0;
}
}
Flood Filling Distance Matrix
Walls and Gates
Multi-end BFS
先找0
然后bfs
每次查看pop出来的坐标的邻居,如果还有INF,就更新距离
public void wallsAndGates(int[][] rooms) {
if(rooms == null || rooms.length == 0 || rooms[0].length == 0) return;
int rows = rooms.length;
int cols = rooms[0].length;
Queue<Integer> gates = new LinkedList<>();
for(int i = 0; i < rows; i++){
for(int j = 0; j< cols; j++){
if(rooms[i][j] == 0){
gates.offer(i * cols + j);//no need to store Tuple
}
}
}
int[] dir = {0,1,0,-1,0};//little trick
while(!gates.isEmpty()){
int gate = gates.poll();
int x = gate / cols;//extract x and y
int y = gate % cols;
for(int i = 0; i < 4; i++){
int xx = x + dir[i];
int yy = y + dir[i + 1];
if(xx >= 0 && xx < rows && yy >= 0 && yy < cols && rooms[xx][yy] == Integer.MAX_VALUE){
rooms[xx][yy] = rooms[x][y] + 1;
gates.offer(xx * cols + yy);
}
}
}
}
给一个2D matrix, 0表示路,1表示墙,给个start point和end point,求最短路径。(Twitter)
最经典的BFS
public class Solution{
public static class Point{
int x;
int y;
public Point(int x, int y){
this.x = x;
this.y = y;
}
}
public static int getDistance(int[][] matrix, Point src, Point dst){
int rows = matrix.length;
int cols = matrix[0].length;
boolean[][] visited = new boolean[rows][cols];
int[][] res = new int[rows][cols];
//4 directions
int[] x_ways = {0,0,1,-1};
int[] y_ways = {1,-1,0,0};
Queue<Point> queue = new LinkedList<>();
queue.offer(src);
while(!queue.isEmpty()){
Point cur = queue.poll();
visited[cur.x][cur.y] = true;
if(cur.x == dst.x && cur.y == dst.y){
break;//find the dst Point
}
for(int i = 0; i < 4; i++){
int x_next = cur.x + x_ways[i];
int y_next = cur.y + y_ways[i];
if(x_next >= 0 && x_next < rows && y_next >= 0 && y_next < cols && matrix[x_next][y_next] == 1 && !visited[x_next][y_next]){
queue.offer(new Point(x_next, y_next));
res[x_next][y_next] = res[cur.x][cur.y] + 1;//distance + 1
}
}
}
if(res[dst.x][dst.y] == 0){
return -1;//no path to dst Point
}
return res[dst.x][dst.y];
}
public static void main(String[] args){
int[][] matrix = {{1,1,1,1,1},
{0,0,1,1,1},
{1,1,1,1,1}
};
int distance = getDistance(matrix, new Point(0,0), new Point(2, 4));
System.out.println("shortest distance between A and B is: " + distance);
}
}
Last updated
Was this helpful?