Decode Algorithms & LeetCode
  • Decode Algorithms & LeetCode
  • G家练习
  • Array
    • Two Sum
    • Two Pointers
    • PrefixSum
    • Matrix
    • Interval & Sweepline
    • Sort
    • Iterator
    • Segment Tree
  • Binary Search
    • 教学
    • Binary Search on Matrix
    • Binary Search To Find An Answer
  • String
    • Parenthesis
    • Sliding Window
    • Trie
  • LinkedList
  • Tree
    • Level Order Traversal
    • BST or Inorder
    • Construst Tree
  • Stack
  • Heap
  • Greedy
  • BFS
  • DFS
    • DFS on String
    • Backtracking
    • DFS+Memo
  • Graph
    • Union Find
    • Topological Sort
    • Dijkstra
    • Bipartite Graph
  • Dynamic Programing
    • DP on String
    • Knapsack Problem
  • Design
    • Concurrency
  • Math
  • Bit Manipulation
Powered by GitBook
On this page

Was this helpful?

BFS

PreviousGreedyNextDFS

Last updated 4 years ago

Was this helpful?

    public boolean canVisitAllRooms(List<List<Integer>> rooms) {
        if (rooms == null || rooms.size() == 0) {
            return true;
        }
        Set<Integer> visited = new HashSet<>();
        Queue<Integer> q = new LinkedList<>();
        q.offer(0);
        visited.add(0);
        while (!q.isEmpty()) {
            int curt = q.poll();
            for (int next : rooms.get(curt)) {
                if (!visited.contains(next)) {
                    q.offer(next);
                    visited.add(next);
                }
            }
        }
        return visited.size() == rooms.size();
    }
    public int shortestPathBinaryMatrix(int[][] grid) {
        int n = grid.length;
        if (grid[0][0] != 0 || grid[n - 1][n - 1] != 0) return -1;
        if (grid.length == 1 && grid[0][0] == 0) return 1;
        boolean[][] visited = new boolean[n][n];
        visited[0][0] = true;
        int[][] dir = new int[][]{{0, 1}, {1, 0}, {0, -1}, {-1, 0},{1,1}, {-1,-1}, {1,-1}, {-1,1}};
        Queue<int[]> q = new LinkedList<>();
        q.offer(new int[]{0, 0});
        int step = 1;
        while (!q.isEmpty()) {
            int size = q.size();
            for (int i = 0; i < size; i++) {
                int[] curt = q.poll();
                for (int[] d : dir) {
                    int nx = curt[0] + d[0];
                    int ny = curt[1] + d[1];
                    if (inbound(grid, nx, ny) && !visited[nx][ny] && grid[nx][ny] == 0) {
                        if (nx == n - 1 && ny == n - 1) return step + 1;
                        visited[nx][ny] = true;
                        q.offer(new int[]{nx, ny});
                    }
                }
            }
            step++;
        }
        return -1;
    }
    
    private boolean inbound(int[][] m, int x, int y) {
        return x >= 0 && y >= 0 && x < m.length && y < m[0].length;
    }

Count the number of oranges and rotten oranges. Starting with all rotten oranges in the queue, traverse in level order to fill all good oranges. Return the number of levels if the all oranges are rotten (check count).

int[][] dirs = new int[][]{{0,1}, {1,0}, {0,-1}, {-1,0}};
public int orangesRotting(int[][] grid) {
    int m = grid.length, n = grid[0].length;
    Queue<int[]> q = new LinkedList<>();
    int count = 0;
    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) {
            if (grid[i][j] == 2) q.offer(new int[]{i, j});
            else if (grid[i][j] == 1) count++;
        }
    }
    if (count == 0) return 0;
    int step = 0;
    while (!q.isEmpty()) {
        int size = q.size();
        for (int i = 0; i < size; i++) {
            int[] curt = q.poll();
            for (int[] d : dirs) {
                int nx = curt[0] + d[0];
                int ny = curt[1] + d[1];
                if (nx >= 0 
                    && nx < m 
                    && ny >= 0 
                    && ny < n 
                    && grid[nx][ny] == 1) {
                    grid[nx][ny] = 2;
                    count--;
                    q.offer(new int[]{nx, ny});
                }
            }
        }
        step++;
    }
    return count == 0 ? step - 1 : -1;
}
    directions = [[0,1],[1,0],[-1,0], [0,-1]]
    def orangesRotting(self, grid: List[List[int]]) -> int:
        queue = []
        orange = 0
        for x in range(0, len(grid)):
            for y in range(0, len(grid[0])):
                if grid[x][y] == 2:
                    queue.append([x, y])
                if grid[x][y] == 1:
                    orange += 1
        if orange == 0:
            return 0
        level = 0
        while queue:
            size = len(queue)
            for k in range(0, size):
                curtx, curty = queue.pop(0)
                if grid[curtx][curty] == 1:
                    grid[curtx][curty] = 2
                    orange -= 1
                    if orange == 0:
                        return level
                for d in self.directions:
                    nx = curtx + d[0]
                    ny = curty + d[1]
                    if self.inbound(grid, nx, ny) and grid[nx][ny] == 1:
                        queue.append([nx, ny])
            level += 1
        if orange == 0:
            return level
        return -1
        
    def inbound(self, grid, x, y) :
        return x >= 0 and x < len(grid) and y >= 0 and y < len(grid[0]) 

Given a 2D boolean array where true represents water and false represents land, generate a grid with highest possible peak. Rules are:

  1. the height of any water cell is 0.

  2. the height of any land cell cannot differ for more than one from any of the neighboring (sharing one edge) cells.

Add all "T" nodes into a BFS queue and trigger a BFS from all those nodes. Also, maintain the distance used to reach each node alongside. Once the BFS visits all the nodes, return the distance to reach every node as the answer.

For the followup:- From all the nodes that have reached max peak height, trigger another BFS that goes from max peak height node to other nodes decrementing the distance. This would lead to more nodes having a height of 0

    int[][] directions = new int[][]{{0,1}, {1,0}, {0,-1}, {-1,0}};
    public int maxDistance(int[][] grid) {
        if(grid == null || grid.length == 0 || grid[0].length == 0) return -1;
        int m = grid.length, n = grid[0].length;
        int[][] dist = new int[m][n];
        Queue<int[]> q = new LinkedList<>();
        Set<Integer> visited = new HashSet<>();
        int count0 = 0, count1 = 0;
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (grid[i][j] == 1) {
                    q.offer(new int[]{i, j});
                    visited.add(i * n + j);
                    count1++;
                } else {
                    count0++;
                }
            }
        }
        int res = -1;
        if (count0 == 0 || count1 == 0) return res;
        int level = -1;
        while (!q.isEmpty()) {
            int size = q.size();
            for (int i = 0; i < size; i++) {
                int[] curt = q.poll();
                for (int[] d : directions) {
                    int nx = curt[0] + d[0];
                    int ny = curt[1] + d[1];
                    if (inbound(grid, nx, ny) 
                        && !visited.contains(nx * n + ny) && grid[nx][ny] == 0) {
                            q.offer(new int[]{nx, ny});
                            visited.add(nx * n + ny);
                    }
                }
            }
            level++;
        }
        return level;
    }
    
    private boolean inbound(int[][] matrix, int x, int y) {
        return x >= 0 && y >= 0 && x < matrix.length && y < matrix[0].length;
    }
    directions = [[0,1],[1,0],[-1,0], [0,-1]]
    def wallsAndGates(self, rooms: List[List[int]]) -> None:
        queue = []
        for x in range(0, len(rooms)):
            for y in range(0, len(rooms[0])):
                if (rooms[x][y] == 0):
                    queue.append([x, y])
        level = 0
        while queue:
            size = len(queue)
            for k in range(0, size):
                curtx, curty = queue.pop(0)
                if rooms[curtx][curty] == 2147483647:
                    rooms[curtx][curty] = level
                for d in self.directions:
                    nx = curtx + d[0]
                    ny = curty + d[1]
                    if self.inbound(rooms, nx, ny) and rooms[nx][ny] == 2147483647:
                        queue.append([nx, ny])
            level += 1
        return
    
    def inbound(self, grid, x, y) :
        return x >= 0 and x < len(grid) and y >= 0 and y < len(grid[0]) 
    directions = [[0,1],[1,0],[-1,0], [0,-1]]
    def solve(self, board: List[List[str]]) -> None:
        if not board or len(board) == 0 or len(board[0]) == 0:
            return
        m = len(board)
        n = len(board[0])
        queue = []
        for i in range(0, m):
            if board[i][0] == "O":
                queue.append([i, 0])
            if board[i][n - 1] == "O":
                queue.append([i, n - 1])
        for j in range(0, n):
            if board[0][j] == "O":
                queue.append([0, j])
            if board[m - 1][j] == "O":
                queue.append([m - 1, j])
        while queue:
            x, y = queue.pop(0)
            board[x][y] = "B"  
            for d in self.directions:  ## x= 3,y=1
                nx = x + d[0]
                ny = y + d[1]
                if self.inbound(board, nx, ny) and board[nx][ny] == "O":
                    queue.append([nx, ny])
        
        for i in range(0, m):
            for j in range(0, n):
                if board[i][j] == "O":
                    board[i][j] = "X"
                if board[i][j] == "B":
                    board[i][j] = "O"
        
    
    def inbound(self, grid, x, y) :
        return x >= 0 and x < len(grid) and y >= 0 and y < len(grid[0]) 
public int shortestPath(List<UndirectedGraphNode> graph, UndirectedGraphNode A, UndirectedGraphNode B) {
        // Write your code here
		Queue<UndirectedGraphNode> q = new LinkedList<>();
		Set<UndirectedGraphNode> visited = new HashSet<>();
		q.offer(A);
		visited.add(A);
		int level = 0;
		while (!q.isEmpty()) {
		    level++;
		    int size = q.size();
		    for (int i = 0; i < size; i++) {
		        UndirectedGraphNode curt = q.poll();
		        for (UndirectedGraphNode next : curt.neighbors) {
		            if (next == B) {
		                return level;
		            }
		            if (visited.contains(next)) {
		                continue;
		            }
		            visited.add(next);
		            q.offer(next);
		        }
		    }
		}
		return -1;
}
    def crawl(self, startUrl: str, htmlParser: 'HtmlParser') -> List[str]:
        visit = set()
        queue = []
        queue.append(startUrl)
        visit.add(startUrl)
        host = startUrl.split("/")[2]
        res = []
        while queue:
            curt = queue.pop(0)
            res.append(curt)
            for next in htmlParser.getUrls(curt):
                if next not in visit and host in next:
                    queue.append(next)
                    visit.add(next)
        return res
    public List<String> crawl(String startUrl, HtmlParser htmlParser) {
        Set<String> visited = new HashSet<>();
        String hostname = startUrl.split("/")[2];
        Queue<String> q = new LinkedList<>();
        q.offer(startUrl);
        while (!q.isEmpty()) {
            String curt = q.poll();
            visited.add(curt);
            for (String next : htmlParser.getUrls(curt)) {
                if (next.indexOf(hostname) != -1 && !visited.contains(next)) {
                    q.offer(next);
                }
            }
        }
        return new ArrayList<>(visited);
    }
    int[][] directions = new int[][]{{0,1}, {1,0}, {0,-1}, {-1,0}};
    public List<List<Integer>> pacificAtlantic(int[][] matrix) {
        if (matrix == null || matrix.length == 0 || matrix[0].length == 0) return new ArrayList<>();
        int m = matrix.length, n = matrix[0].length;
        boolean[][] pacific = new boolean[m][n];
        boolean[][] atlantic = new boolean[m][n];
        List<List<Integer>> result = new ArrayList<>();
        Queue<int[]> q_P = new LinkedList<>();
        Queue<int[]> q_A = new LinkedList<>();
        for (int i = 0; i < matrix.length; i++) {
            for (int j = 0; j < matrix[0].length; j++) {
                if (i == 0 || j == 0) {
                    q_P.offer(new int[]{i, j});
                    pacific[i][j] = true;
                }
                if (i == m - 1 || j == n - 1) {
                    q_A.offer(new int[]{i, j});
                    atlantic[i][j] = true;
                }
            }
        }
        BFS(matrix, q_P, pacific);
        BFS(matrix, q_A, atlantic);
        for (int i = 0; i < matrix.length; i++) {
            for (int j = 0; j < matrix[0].length; j++) {
                if (pacific[i][j] && atlantic[i][j]) {
                    result.add(Arrays.asList(new Integer[]{i, j}));    
                }
            }
        }
        return result;
    }
    
    private void BFS(int[][] matrix, Queue<int[]> q, boolean[][] visited) {
        while (!q.isEmpty()) {
            int size = q.size();
            for (int i = 0; i < size; i++) {
                int[] curt = q.poll();
                int x = curt[0], y = curt[1];
                for (int[] d : directions) {
                    int nx = x + d[0];
                    int ny = y + d[1];
                    if (inbound(matrix, nx, ny)
                        && matrix[nx][ny] >= matrix[x][y]
                        && !visited[nx][ny]) {
                        visited[nx][ny] = true;
                        q.offer(new int[]{nx, ny});
                    }
                }
            }
        }
    }
    
    private boolean inbound(int[][] matrix, int x, int y) {
        return x >= 0 && y >= 0 && x < matrix.length && y < matrix[0].length;
    }

Build graph by using stop to next available stops. Level order BFS to find the next stops, return step/level when reach stop T. (This answer will return TLE when there are too many stops)

   public int numBusesToDestination(int[][] routes, int S, int T) {
        Map<Integer, Set<Integer>> map = new HashMap<>();
        for (int[] route : routes) {
            for (int i = 0; i < route.length; i++) {
                for (int j = 0; j < route.length; j++) {
                    if (i == j) continue;
                    map.putIfAbsent(route[i], new HashSet<>());
                    map.putIfAbsent(route[j], new HashSet<>());
                    map.get(route[i]).add(route[j]);
                    map.get(route[j]).add(route[i]);
                }
            }
        }
        Queue<Integer> q = new LinkedList<>();
        Set<Integer> visited = new HashSet<>();
        q.offer(S);
        int level = 0;
        while (!q.isEmpty()) {
            int size = q.size();
            for (int i = 0; i < size; i++) {
                int curt = q.poll();
                if (curt == T) return level;
                if (map.get(curt) == null) continue;
                for (int next : map.get(curt)) {
                    if (next == T) return level + 1;
                    if (visited.contains(next)) continue;
                    visited.add(next);
                    q.offer(next);
                }
            }
            level++;
        }
        return -1;
    }

One modification is to check duplicate on bus route, instead of bus stops. That will eliminate lots of path since all stops on traveled path are redundant.

    public int numBusesToDestination(int[][] routes, int S, int T) {
        if (S == T) return 0;
        Map<Integer, Set<Integer>> map = new HashMap<>(); // stop : buses
        Queue<Integer> q = new LinkedList<>();
        for (int i = 0; i < routes.length; i++) {
            for (int n : routes[i]) {
                map.putIfAbsent(n, new HashSet<>());
                map.get(n).add(i);
            }
        }
        if (!map.containsKey(S)) return -1;
        Set<Integer> visited = new HashSet<>(); 
        int count = 0;
        q.offer(S);
        while (!q.isEmpty()) {
            int size = q.size();
            for (int k = 0; k < size; k++) {
                int curt = q.poll();
                if (curt == T) return count + 1;
                for (int r : map.get(curt)) {
                    if (visited.contains(r)) continue;
                    visited.add(r);
                    for (int next : routes[r]) {
                        if (next == T) return count + 1;
                        q.offer(next);
                    }
                }
            }
            count++;
        }
        return -1;
    }

N is number of stops, T is the stops * edges: T: O(n^2)

Find the next node by extending the directions, until reach boundary or wall. Use boolean[][] visited to record all visited nodes.

    int[][] dirs = {{1,0} , {0,1}, {-1,0}, {0,-1}};
    public boolean hasPath(int[][] maze, int[] start, int[] destination) {
        boolean[][] visited = new boolean[maze.length][maze[0].length];
        Queue<int[]> q = new LinkedList<>();
        q.offer(start);
        visited[start[0]][start[1]] = true;
        while (!q.isEmpty()) {
            int[] curt = q.poll();
            if (curt[0] == destination[0] && curt[1] == destination[1]) {
                return true;
            }
            for (int[] dir : dirs) {
                int x = curt[0];
                int y = curt[1];
                while (inbound(maze, x + dir[0], y + dir[1]) 
                       && maze[x + dir[0]][y + dir[1]] != 1) {
                    x += dir[0];
                    y += dir[1];
                }
                if (x == destination[0] && y == destination[1]) {
                    return true;
                }
                if (!visited[x][y]) {
                    visited[x][y] = true;
                    q.offer(new int[]{x, y});
                }
            }
        }
        return false;
    }
    
    private boolean inbound(int[][] maze, int x, int y) {
        return x >= 0 && y >= 0 && x < maze.length && y < maze[0].length;
    }

The BFS solution requires to store all path to destination. Use a dist matrix to store the minimum distance between each grid and start point. Replace the distance when new calculated steps is less than the earlier calculations. Output result as all distances are calculated.

int[][] direction = new int[][]{{1,0}, {0,1}, {-1,0}, {0,-1}};
public int shortestDistance(int[][] maze, int[] start, int[] destination) {
    if (start == null || destination == null || maze == null || maze.length == 0 || maze[0].length == 0) {
        return -1;
    }
    int m = maze.length, n = maze[0].length;
    int[][] dist = new int[m][n];
    for (int[] row : dist) Arrays.fill(row, Integer.MAX_VALUE);

    Queue<int[]> q = new LinkedList<>();
    q.offer(start);
    dist[start[0]][start[1]] = 0;
    while (!q.isEmpty()) {
        int[] curt = q.poll();
        for (int[] d : direction) {
            int nx = curt[0];
            int ny = curt[1];
            int step = 0;
            while (inbound(maze, nx + d[0], ny + d[1]) && maze[nx + d[0]][ny + d[1]] == 0) {
                nx += d[0];
                ny += d[1];
                step++;
            }
            if (dist[nx][ny] > dist[curt[0]][curt[1]] + step) {
                dist[nx][ny] = dist[curt[0]][curt[1]] + step;
                q.offer(new int[]{nx, ny});
            }
        }
    }
    return dist[destination[0]][destination[1]] == Integer.MAX_VALUE ? -1 
                                : dist[destination[0]][destination[1]];
}

private boolean inbound(int[][] grid, int x, int y) {
    return x >= 0 && x < grid.length && y >= 0 && y < grid[0].length;
}

Given a knight in a chessboard (a binary matrix with 0as empty a 1as barrier) with a source position, find the shortest path to a destination position, return the length of the route.

Return -1 if knight can not reached.

Notice

  • Source and destination must be empty.

  • Knight can not enter the barrier.

    int[][] directions = {{1, 2}, {2, 1}, {-1, 2}, {-2, 1},
            {1, -2}, {2, -1}, {-1, -2}, {-2, -1}};
    public int knightshortestpath(int[][] grid, int[] start, int[] destination) {
        if(grid == null || grid.length == 0 ||
                grid[0].length == 0 || start == null || destination == null){
            return -1;
        }
        if (start[0] == destination[0] && start[1] == destination[1]) {
            return 0;
        }
        Queue<int[]> queue = new LinkedList<>();
        queue.offer(start);
        grid[start[0]][start[1]] = 2;
        int level = 0;
        while (!queue.isEmpty()) {
            int size = queue.size();
            for (int i = 0; i < size; i++) {
                int[] curt = queue.poll();
                for (int[] d : directions) {
                    int nx = curt[0] + d[0];
                    int ny = curt[1] + d[1];
                    if (nx == destination[0] && ny == destination[1]) {
                        return level + 1;
                    }
                    if (inbound(grid, nx, ny) && grid[nx][ny] == 0) {
                        grid[nx][ny] = 2;
                        queue.offer(new int[]{nx, ny});
                    }
                }
            }
            level++;
        }
        return -1;
    }

    private boolean inbound(int[][] grid, int x, int y) {
        return x >= 0 && x < grid.length && y >= 0 && y < grid[0].length;
    }

Fill the result matrix with Integer.MAX_VALUE to detect if the node has been visited. Starting from 0 grids, use BFS to detect if the next distance from 0 is larger than expected, if so, correct it to the right value. Offer that next node to the queue.

T: O(m * n) S: O(m * n)

    int[][] dirs = {{1,0} , {0,1}, {-1,0}, {0,-1}};
    public int[][] updateMatrix(int[][] matrix) {
        Queue<int[]> q = new LinkedList<>();
        for (int i = 0; i < matrix.length; i++) {
            for (int j = 0; j < matrix[0].length; j++) {
                if (matrix[i][j] == 0) {
                    q.offer(new int[]{i, j});
                } else {
                    matrix[i][j] = Integer.MAX_VALUE;
                }
            }
        }
        while (!q.isEmpty()) {
            int[] curt = q.poll();
            for (int[] d : dirs) {
                int nx = curt[0] + d[0];
                int ny = curt[1] + d[1];
                if (inbound(matrix, nx, ny) && matrix[nx][ny] > matrix[curt[0]][curt[1]] + 1) {
                    matrix[nx][ny] = matrix[curt[0]][curt[1]] + 1;
                    q.offer(new int[]{nx, ny});
                }
            }
        }
        return matrix;
    }
    
    private boolean inbound(int[][] matrix, int x, int y) {
        return x >= 0 && y >= 0 && x < matrix.length && y < matrix[0].length;
    }

T: O(k^2 * N) N is number of words and k is the average length of words

    public int ladderLength(String beginWord,
                            String endWord,
                            List<String> wordList) {
        if (beginWord == null || endWord == null 
                || beginWord.isEmpty() || endWord.isEmpty()) {
            return 0;
        }
        if (beginWord.equals(endWord)) return 0;
        Set<String> dict = new HashSet<>();
        dict.addAll(wordList);
        if (!dict.contains(endWord)) return 0;
        Set<String> visited = new HashSet<>();
        visited.add(beginWord);
        Queue<String> q = new LinkedList<>();
        q.offer(beginWord);
        int level = 1;
        while (!q.isEmpty()) {
            int size = q.size();
            for (int i = 0; i < size; i++) {
                String curt = q.poll();
                for (String next : getNexts(curt, dict)) {
                    if (next.equals(endWord)) return level + 1;
                    if (visited.contains(next)) continue;
                    visited.add(next);
                    q.offer(next);
                }
            }
            level++;
        }
        return 0;
    }
    
    private Set<String> getNexts(String s, Set<String> dict) {
        Set<String> result = new HashSet<>();
        char[] chars = s.toCharArray();
        for (int i = 0; i < chars.length; i++) {
            char old = chars[i];
            for (char c = 'a'; c <= 'z'; c++) {
                chars[i] = c;
                String next = String.valueOf(chars);
                if (dict.contains(next)) result.add(next);
            }
            chars[i] = old;
        }
        return result;
    }
    def ladderLength(self, beginWord: str, endWord: str, wordList: List[str]) -> int:
        dic = set(wordList)
        if endWord not in dic:
            return 0
        queue = []
        visit = set()
        queue.append(beginWord)
        visit.add(beginWord)
        level = 1
        while queue:
            size = len(queue)
            for i in range(size):
                curt = queue.pop(0)
                for next in self.getNext(curt, dic, visit):
                    if next == endWord:
                        return level + 1
                    if next in dic and next not in visit:
                        visit.add(next)
                        queue.append(next)
            level += 1
        return 0
    
    def getNext(self, s, dic, visit):
        res = []
        for i in range(len(s)):
            for c in 'abcdefghijklmnopqrstuvwxyz':
                new = s[:i] + c + s[i + 1:]
                if new in dic and new not in visit:
                    res.append(new)
        return res

Use BFS level order traversal to build graph and record distance from start node. DFS to build path.

    public List<List<String>> findLadders(String beginWord, String endWord, List<String> wordList) {
        Map<String, Integer> dist = new HashMap<>();
        Map<String, Set<String>> graph = new HashMap<>();
        Set<String> dict = new HashSet<>();
        dict.addAll(wordList);
        List<List<String>> res = new ArrayList<>();
        if (!dict.contains(endWord) || beginWord.equals(endWord)) return res;
        bfsBuildGraph(beginWord, endWord, dict, dist, graph);
        List<String> list = new ArrayList<>();
        list.add(beginWord);
        dfs(beginWord, endWord, list, res, dist, graph);
        return res;
    }

    private void dfs(String curt,
                     String target,
                     List<String> list,
                     List<List<String>> result,
                     Map<String, Integer> dist,
                     Map<String, Set<String>> graph) {
        if (curt.equals(target)) {
            result.add(new ArrayList<>(list));
            return;
        }
        if (graph.get(curt) == null) return;
        for (String next : graph.get(curt)) {
            if (dist.get(next) == dist.get(curt) + 1) {
                list.add(next);
                dfs(next, target, list, result, dist, graph);
                list.remove(list.size() - 1);
            }
        }
    }

    private void bfsBuildGraph(String beginWord,
                              String endWord,
                              Set<String> dict,
                               Map<String, Integer> dist,
                               Map<String, Set<String>> graph) {
        Queue<String> q = new LinkedList<>();
        q.offer(beginWord);
        dist.put(beginWord, 0);
        boolean foundEnd = false;
        while (!q.isEmpty()) {
            int size = q.size();
            for (int i = 0; i < size; i++) {
                String curt = q.poll();
                int d = dist.get(curt);
                graph.putIfAbsent(curt, new HashSet<>());
                for (String next : getNexts(curt, dict)) {
                    graph.get(curt).add(next);
                    if (next.equals(endWord)) foundEnd = true;
                    if (dist.containsKey(next)) continue;
                    dist.put(next, d + 1);
                    q.offer(next);
                }
            }
            if (foundEnd) break;
        }
    }
    
    private Set<String> getNexts(String s, Set<String> dict) {
        Set<String> result = new HashSet<>();
        char[] chars = s.toCharArray();
        for (int i = 0; i < chars.length; i++) {
            char old = chars[i];
            for (char c = 'a'; c <= 'z'; c++) {
                chars[i] = c;
                String next = String.valueOf(chars);
                if (dict.contains(next)) result.add(next);
            }
            chars[i] = old;
        }
        return result;
    }

Use a map to store the relationship key: current node value: corresponding new node. Traverse the graph with a curt node and add corresponding neighbors to the neighbors list.

T: O(n)

    public Node cloneGraph(Node node) {
        if (node == null) return null;
        Map<Node, Node> map = new HashMap<>();
        Queue<Node> q = new LinkedList<>();
        map.put(node, new Node(node.val, new ArrayList<>()));
        q.offer(node);
        while (!q.isEmpty()) {
            Node curt = q.poll();
            for (Node next : curt.neighbors) {
                if (!map.containsKey(next)) {
                    map.put(next, new Node(next.val, new ArrayList<>()));
                    q.offer(next);
                }
                map.get(curt).neighbors.add(map.get(next));
            }
        }
        return map.get(node);
    }
    def cloneGraph(self, node: 'Node') -> 'Node':
        if not node:
            return None
        dic = {}
        visited = set()
        queue = []
        queue.append(node)
        visited.add(node)
        dic[node] = Node(node.val)
        while queue:
            curt = queue.pop(0)
            for next in curt.neighbors:
                if next not in visited:
                    dic[next] = Node(next.val)
                    queue.append(next)
                    visited.add(next)
                dic[curt].neighbors.append(dic[next])
        return dic[node]
    public boolean validTree(int n, int[][] edges) {
        if (edges.length != n - 1) {
            return false;
        }
        Map<Integer, Set<Integer>> map = new HashMap<>();
        for (int[] edge : edges) {
            int u = edge[0], v = edge[1];
            map.putIfAbsent(u, new HashSet<>());
            map.putIfAbsent(v, new HashSet<>());
            map.get(u).add(v);
            map.get(v).add(u);
        }
        Set<Integer> visited = new HashSet<>();
        Queue<Integer> q = new LinkedList<>();
        q.offer(0);
        visited.add(0);
        while (!q.isEmpty()) {
            int curt = q.poll();
            if (map.get(curt) == null) continue;
            for (int next : map.get(curt)) {
                map.get(next).remove(curt);
                if (visited.contains(next)) {
                    return false;
                }
                visited.add(next);
                q.offer(next);
            }
        }
        return visited.size() == n;
    }
    def validTree(self, n: int, edges: List[List[int]]) -> bool:
        if n != len(edges) + 1:
            return False
        graph = [[] for i in range(n)]
        indegree = [0] * n
        for v, u in edges:
            graph[u].append(v)
            graph[v].append(u)
            
        queue = []
        visited = set()
        queue.append(0)
        visited.add(0)
        while queue:
            curt = queue.pop(0)
            for next in graph[curt]:
                if next in visited:
                    return False
                graph[next].remove(curt)
                visited.add(next)
                queue.append(next)
        return len(visited) == n

Convert index to board by using:

  • int row = n - (next - 1) / n - 1

  • int col = (n - row) % 2 != 0 ? (next - 1) % n : n - (next - 1) % n - 1

    public int snakesAndLadders(int[][] board) {
        if (board == null || board.length == 0) return 0;
        int n = board.length;
        Queue<Integer> q = new LinkedList<>();
        Set<Integer> visited = new HashSet<>();
        q.offer(1);
        visited.add(1);
        int step = 0, min = Integer.MAX_VALUE;
        while (!q.isEmpty()) {
            int size = q.size();
            for (int i = 0; i < size; i++) {
                int curt = q.poll();
                if (curt == n * n) min = Math.min(min, step);
                for (int k = 1; k <= 6; k++) {
                    int next = curt + k;
                    if (next > n * n) break;
                    if (visited.contains(next)) continue;
                    visited.add(next);
                    int row = n - (next - 1) / n - 1;
                    int col = (n - row) % 2 != 0 ? (next - 1) % n
                                                 : n - (next - 1) % n - 1;
                    if (board[row][col] == curt) continue;
                    if (board[row][col] == -1) {
                        q.offer(next);
                    } else {
                        q.offer(board[row][col]);
                    }
                }
            }
            step++;
        } 
        return min == Integer.MAX_VALUE ? -1 : min;
    }

Similar as 127. Word Ladder.

    public int openLock(String[] deadends, String target) {
        Set<String> deads = new HashSet<>();
        for (String d : deadends) {
            if (d.equals("0000")) {
                return -1;
            }
            deads.add(d);
        }
        Queue<String> queue = new LinkedList<>();
        Set<String> visited = new HashSet<>();
        queue.offer("0000");
        visited.add("0000");
        int level = 0;
        while (!queue.isEmpty()) {
            int size = queue.size();
            for (int i = 0; i < size; i++) {
                String curt = queue.poll();
                if (curt.equals(target)) return level;
                for (String next : getNexts(curt, deads, visited)) {
                    if (visited.contains(next)) {
                        continue;
                    }
                    visited.add(next);
                    queue.offer(next);
                }
            }
            level++;
        }
        return -1;
    }

   private Set<String> getNexts(String curt, Set<String> deads, Set<String> visited) {
     Set<String> nextCurs = new HashSet<>();
        char[] chars = curt.toCharArray();
        for (int i = 0; i < 4; i++) {
            char origin = chars[i];
            chars[i] = (char)((origin - '0' + 1) % 10 + '0');
            String next = new String(chars);

            if (!deads.contains(next) && !visited.contains(next)) {
                nextCurs.add(next);
            }
            chars[i] = (char)((origin - '0' - 1 + 10) % 10 + '0');
            next = new String(chars);

            if (!deads.contains(next) && !visited.contains(next)) {
                nextCurs.add(next);
            }
            chars[i] = origin;
        }
        return nextCurs;
    }
    def openLock(self, deadends: List[str], target: str) -> int:
        start = "0000"
        dead = set(deadends)
        if start in dead:
            return -1
        visited = set()
        queue = []
        queue.append(start)
        visited.add(start)
        level = 0
        while queue:
            level += 1
            size = len(queue)
            for i in range(size):
                curt = queue.pop(0)
                for next in self.getnexts(curt):
                    if target == next:
                        return level
                    if next not in visited and next not in dead:
                        queue.append(next)
                        visited.add(next)
        return -1
        
    
    def getnexts(self, s):
        for i in range(4):
            yield s[:i] + str((int(s[i]) + 1) % 10) + s[i+1:]
            yield s[:i] + str((int(s[i]) - 1) % 10) + s[i+1:]

Check on curt get TLE, however check both on curt and next should work.

    Map<Integer, Integer> map;
    public int confusingNumberII(int N) {
        map = new HashMap<>();
        map.put(0, 0);
        map.put(1, 1);
        map.put(6, 9);
        map.put(8, 8);
        map.put(9, 6);
        Queue<Integer> q = new LinkedList<>();
        q.offer(0);
        int count = 0;
        Set<Integer> set = new HashSet<>();
        set.add(0);
        while (!q.isEmpty()) {
            int curt = q.poll();
            for (int d : map.keySet()) {
                int next = curt * 10 + d;
                if (next > N) return count; 
                if (next != 0) {
                    q.offer(next);
                }
                if (isConfusing(next) && !set.contains(next)) {
                    set.add(next);
                    count++;
                }
            }
        }
        return count;
    }
    
    private boolean isConfusing(int n) {
        long rot = 0;
        int tmp = n;
        while (n > 0) {
            rot = rot * 10 + map.get(n % 10);
            n /= 10;
        }
        return rot != tmp;
    }
    Map<Integer, Integer> map;
    public int confusingNumberII(int N) {
        map = new HashMap<>();
        map.put(0, 0);
        map.put(1, 1);
        map.put(6, 9);
        map.put(8, 8);
        map.put(9, 6);
        Queue<Integer> q = new LinkedList<>();
        q.offer(0);
        int count = 0;
        Set<Integer> set = new HashSet<>();
        while (!q.isEmpty()) {
            int curt = q.poll();
            if (curt > N) break; 
            if (isConfusing(curt) && !set.contains(curt)) {
                set.add(curt);
                count++;
            }
            for (int d : map.keySet()) {
                q.offer(curt * 10 + d);
            }
        }
        return count;
    }
    
    private boolean isConfusing(int n) {
        long rot = 0;
        int tmp = n;
        while (n > 0) {
            rot = rot * 10 + map.get(n % 10);
            n /= 10;
        }
        return rot != tmp;
    }
    public int[] shortestAlternatingPaths(int n, int[][] red_edges, int[][] blue_edges) {
        int[][] graph = new int[n][n];
        buildGraph(graph, n, red_edges, blue_edges);
        Queue<int[]> q = new LinkedList<>();
        Set<String> set = new HashSet<>();
        q.offer(new int[]{0, 1});
        q.offer(new int[]{0, -1});
        
        int[] res = new int[n];
        Arrays.fill(res, Integer.MAX_VALUE);
        res[0] = 0;
        
        int level = 0;
        while (!q.isEmpty()) {
            level++;
            int size = q.size();
            for (int i = 0; i < size; i++) {
                int[] curt = q.poll();
                int node = curt[0], color = curt[1];
                for (int k = 0; k < n; k++) {
                    if (graph[node][k] == 0 || graph[node][k] == -color) {
                        if (!set.add(k + " " + (-color))) continue;
                        q.offer(new int[]{k, -color});
                        res[k] = Math.min(res[k], level);
                    }
                }
            }
        }
        for (int i = 1; i < n; i++) {
            if (res[i] == Integer.MAX_VALUE) {
                res[i] = -1;
            }
        }
        return res;
    }
    
    private void buildGraph(int[][] g, int n, int[][] red_edges, int[][] blue_edges) {
        for (int i = 0; i < n; i++) {
            Arrays.fill(g[i], -n);
        }
        for (int[] e : red_edges) {
            g[e[0]][e[1]] = 1;
        }
        for (int[] e : blue_edges) {
            int from = e[0];
            int to = e[1];
            if (g[from][to] == 1) {
                g[from][to] = 0;
            } else {
                g[from][to] = -1;
            }
        }
    }

bfs level order traverse starts from all buildings, go through all each empty grids, to calculate the cumulated shortest distance from all buildings. Also count how many houses can reach this spot, when output, detect if this spot can be reached by all starting points.

T: O((mn)^2) .S: O(mn)

    int[][] direction = new int[][]{{1,0}, {0,1}, {-1,0}, {0,-1}};
    public int shortestDistance(int[][] grid) {
        if (grid == null || grid.length == 0 || grid[0].length == 0) return -1;
        int m = grid.length, n = grid[0].length;
        int[][] dist = new int[m][n], count = new int[m][n];
        int house = 0;
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (grid[i][j] == 1) {
                    house++;
                    dist[i][j] = -1;
                    bfs(grid, dist, count, i, j);
                } else if (grid[i][j] == 2) {
                    dist[i][j] = -1;
                }
            }
        }
        int min = Integer.MAX_VALUE;
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (dist[i][j] != -1 && grid[i][j] == 0 && count[i][j] == house) {
                    min = Math.min(min, dist[i][j]);
                }
            }
        } 
        return min == Integer.MAX_VALUE ? -1 : min;
    }
    
    private void bfs(int[][] grid, int[][] dist, int[][] count, int x, int y) {
        int n = grid[0].length;
        Set<Integer> set = new HashSet<>();
        Queue<int[]> q = new LinkedList<>();
        set.add(x * n + y);
        q.offer(new int[]{x, y});
        int level = 0;
        while (!q.isEmpty()) {
            level++;
            int size = q.size();
            for (int k = 0; k < size; k++) {
                int[] curt = q.poll();
                for (int[] d : direction) {
                    int nx = curt[0] + d[0];
                    int ny = curt[1] + d[1];
                    if (inbound(nx, ny, grid) 
                        && !set.contains(nx * n + ny) 
                        && grid[nx][ny] != 1 
                        && grid[nx][ny] != 2) {
                        count[nx][ny]++;
                        dist[nx][ny] += level;
                        set.add(nx * n + ny);
                        q.offer(new int[]{nx, ny});
                    }
                }
            }
        }
    }
    
    private boolean inbound(int x, int y, int[][] grid) {
        return x >= 0 && x < grid.length && y >= 0 && y < grid[0].length;
    }
    int x = -1, y = -1;
    int max = -1;
    int[][] direction = new int[][]{{1,0}, {0,1}, {-1,0}, {0,-1}};
    public int shortestPathAllKeys(String[] grid) {
        int m = grid.length, n = grid[0].length();
        char[][] g = new char[m][n];
        for (int i = 0; i < grid.length; i++) {
            g[i] = grid[i].toCharArray();
        }
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (g[i][j] == '@') {
                    x = i;
                    y = j;
                } else if (g[i][j] >= 'a' && g[i][j] <= 'z') {
                    max = Math.max(g[i][j] - 'a' + 1, max);
                }
            }
        }
        Queue<Node> q = new LinkedList<>();
        Set<String> set = new HashSet<>();
        set.add(0 + " " + x + " " + y);
        q.offer(new Node(x, y, 0));
        int level = 0;
        while (!q.isEmpty()) {
            int size = q.size();
            for (int i = 0; i < size; i++) {
                Node curt = q.poll();
                if (curt.keys == Math.pow(2, max) - 1) {
                    return level;
                }
                for (int[] d : direction) {
                    int nx = curt.x + d[0];
                    int ny = curt.y + d[1];
                    int keys = curt.keys;
                    if (inbound(g, nx, ny)) {
                        if (g[nx][ny] == '#') continue;
                        if (g[nx][ny] >= 'a' && g[nx][ny] <= 'z') {
                            keys |= 1 << g[nx][ny] - 'a';
                        }
                        if (g[nx][ny] >= 'A' && g[nx][ny] <= 'Z' && ((keys >> (g[nx][ny] - 'A')) & 1) == 0) {
                            continue;    
                        }
                        if (!set.contains(keys + " " + nx + " " + ny)) {
                            set.add(keys + " " + nx + " " + ny);
                            q.offer(new Node(nx, ny, keys));
                        }
                    }
                }
            }
            level++;
        }
        return -1;
    }
    
    class Node {
        int x, y, keys;
        public Node(int x, int y, int keys) {
            this.x = x;
            this.y = y;
            this.keys = keys;
        }
    }
    
    private boolean inbound(char[][] grid, int x, int y) {
        return x >= 0 && x < grid.length && y >= 0 && y < grid[0].length;
    }
    public int slidingPuzzle(int[][] board) {
        StringBuilder start = new StringBuilder();
        for (int i = 0; i < board.length; i++) {
            for (int j = 0; j < board[0].length; j++) start.append(board[i][j]);
        }
        int[][] nexts = {{1,3}, {0,2,4}, {1,5}, {0,4}, {1,3,5}, {2,4}};
        String target = "123450";
        Queue<String> q = new LinkedList<>();
        Set<String> visited = new HashSet<>();
        visited.add(start.toString());
        q.offer(start.toString());
        int step = 0;
        while (!q.isEmpty()) {
            int size = q.size();
            for (int i = 0; i < size; i++) {
                String curt = q.poll();
                if (curt.equals(target)) return step;
                int zero = curt.indexOf('0');
                if (zero == -1) return -1;
                for (int next : nexts[zero]) {
                    StringBuilder sb = new StringBuilder(curt);
                    char temp = sb.charAt(next);
                    sb.setCharAt(zero, temp);
                    sb.setCharAt(next, '0');
                    String n = sb.toString();
                    if (n.equals(target)) return step + 1;
                    if (visited.contains(n)) continue;
                    q.offer(n);
                    visited.add(n);
                }
            }
            step++;
        }
        return -1;
    }
    int[][] move = {{1,3}, {0,2,4}, {1,5}, {0,4}, {1,3,5}, {2,4}};
    public int slidingPuzzle(int[][] board) {
        String target = "123450";
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < board.length; i++) {
            for (int j = 0; j < board[0].length; j++) {
                sb.append(board[i][j]);
            }
        }
        String start = sb.toString();
        if (start.equals(target)) {
            return 0;
        }
        Queue<String> queue = new LinkedList<>();
        Set<String> visited = new HashSet<>();
        queue.offer(start);
        visited.add(start);
        int level = 0;
        while (!queue.isEmpty()) {
            level++;
            int size = queue.size();
            for (int i = 0; i < size; i++) {
                String curt = queue.poll();
                for (String next : getNext(curt)) {
                    if (next.equals(target)) {
                        return level;
                    }
                    if (!visited.contains(next)) {
                        queue.offer(next);
                        visited.add(next);
                    }
                }
            }
        }
        return -1;
    }
    
    private Set<String> getNext(String s) {
        Set<String> set = new HashSet<>();
        StringBuilder sb = new StringBuilder(s);
        int u = s.indexOf("0");
        char uchar = sb.charAt(u);
        for (int v : move[u]) {
            char vchar = sb.charAt(v);
            sb.setCharAt(v, uchar);
            sb.setCharAt(u, vchar);
            set.add(sb.toString());
            System.out.println(sb.toString());
            sb = new StringBuilder(s);
        }
        return set;
    }
public int shortestPath(int[][] grid, int k) {
    int step = 0;
    int m = grid.length;
    int n = grid[0].length;
    int[][] DIRS = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
    int[][] seen = new int[m][n]; // min obstacles elimination from (0,0) to (x, y)
    for (int i = 0; i < m; i++) {
        Arrays.fill(seen[i], Integer.MAX_VALUE);
    }
    Queue<int[]> q = new LinkedList<>();
    q.offer(new int[]{0, 0, 0});
    seen[0][0] = 0;
    while (!q.isEmpty()) {
        int size = q.size();
        while (size-- > 0) {
            int[] cur = q.poll();
            if (cur[0] == m - 1 && cur[1] == n - 1) {
                return step;
            }
            for (int[] dir : DIRS) {
                int x = dir[0] + cur[0];
                int y = dir[1] + cur[1];
                if (x < 0 || x >= m || y < 0 || y >= n) {
                    continue;
                }
                int o = grid[x][y] + cur[2];
                if (o >= seen[x][y] || o > k) {
                    continue;
                }
                seen[x][y] = o;
                q.offer(new int[]{x, y, o});
            }
        }
        ++step;
    }
    return -1;  
}
    int[][] directions = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
    public int cutOffTree(List<List<Integer>> forest) {
        if (forest == null || forest.size() == 0 || forest.get(0).size() == 0) {
            return -1;
        }
        List<int[]> treeHeights = getAllTreeHights(forest);
        Collections.sort(treeHeights, (a, b) -> (a[2] - b[2]));
        int i = 0;
        int[] pre = new int[]{0, 0};
        int step = 0;
        while (i < treeHeights.size()) {
            int[] curt = treeHeights.get(i);
            int s = getMinimumSteps(forest, pre[0], pre[1], curt[0], curt[1]);
            if (s == -1) return -1;
            step += s;
            pre[0] = curt[0];
            pre[1] = curt[1];
            forest.get(pre[0]).set(pre[1], 1);
            i++;
        }
        return step;
    }

    private int getMinimumSteps(List<List<Integer>> forest, int curX, int curY, int aimX, int aimY) {
        int n = forest.get(0).size();
        Queue<int[]> q = new LinkedList<>();
        Set<Integer> visited = new HashSet<>();
        q.offer(new int[]{curX, curY});
        visited.add(curX * n + curY);
        int level = 0;
        while (!q.isEmpty()) {
            int size = q.size();
            for (int i = 0; i < size; i++) {
                int[] curt = q.poll();
                if (curt[0] == aimX && curt[1] == aimY) {
                    return level;
                }
                for (int[] d : directions) {
                    int nx = curt[0] + d[0];
                    int ny = curt[1] + d[1];
                    if (inbound(forest, nx, ny) && !visited.contains(nx * n + ny) && forest.get(nx).get(ny) != 0) {
                        visited.add(nx * n + ny);
                        q.offer(new int[]{nx, ny});
                    }
                }
            }
            level++;
        }
        return -1;
    }

    private List<int[]> getAllTreeHights(List<List<Integer>> forest) {
        List<int[]> treeHeights = new LinkedList<>();
        for (int i = 0; i < forest.size(); i++) {
            for (int j = 0; j < forest.get(0).size(); j++) {
                int[] res = new int[3];
                res[0] = i;
                res[1] = j;
                res[2] = forest.get(i).get(j);
                if (res[2] > 1) {
                    treeHeights.add(res);
                }
            }
        }
        return treeHeights;
    }
    
    private boolean inbound(List<List<Integer>> forest, int x, int y) {
        return x >= 0 && y >= 0 && x < forest.size() && y < forest.get(0).size();
    }
import collections
class Solution(object):
    def cutOffTree(self, G):
        """
        :type forest: List[List[int]]
        :rtype: int
        """
        if not G or not G[0]: return -1
        m, n = len(G), len(G[0])
        trees = []
        for i in xrange(m):
            for j in xrange(n):
                if G[i][j] > 1:
                    trees.append((G[i][j], i, j))
        trees = sorted(trees)
        count = 0
        cx, cy = 0, 0
        for h, x, y in trees:
            step = self.BFS(G, cx, cy, x, y)
            if step == -1:
                return -1
            else:
                count += step
                G[x][y] = 1
                cx, cy = x, y
        return count

    def BFS(self, G, cx, cy, tx, ty):
        m, n = len(G), len(G[0])
        visited = [[False for j in xrange(n)] for i in xrange(m)]
        Q = collections.deque()
        step = -1
        Q.append((cx, cy))
        while len(Q) > 0:
            size = len(Q)
            step += 1
            for i in xrange(size):
                x, y = Q.popleft()
                visited[x][y] = True
                if x == tx and y == ty:
                    return step
                for nx, ny in [(x + 1, y), (x - 1, y), (x, y-1), (x, y + 1)]:
                    if nx < 0 or nx >= m or ny < 0 or ny >= n or G[nx][ny] == 0 or visited[nx][ny]:
                        continue
                    Q.append((nx, ny))
        return -1

BFS Level order traversal.

public int minJumps(int[] arr) {
    int n = arr.length;
    HashMap<Integer, List<Integer>> indicies = new HashMap<>();
    for (int i = 0; i < n; i++)
        indicies.computeIfAbsent(arr[i], x -> new LinkedList<>()).add(i);
    boolean[] visited = new boolean[n];
    Queue<Integer> q = new LinkedList<>();
    q.offer(0);
    int level = 0;
    visited[0] = true;
    while (!q.isEmpty()) {
        int size = q.size();
        for (int i = 0; i < size; i++) {
            int index = q.poll();
            if (index == n - 1) {
                return level;
            }
            List<Integer> nexts = indicies.get(arr[index]);
            nexts.add(index + 1);
            nexts.add(index - 1);
            for (int next : nexts) {
                if (next >= 0 && next < n && !visited[next] && next != index) {
                    q.offer(next);
                    visited[next] = true;
                }
            }
            nexts.clear();
        }
        level++;
    }
    return -1;
}

DFS

841. Keys and Rooms
1091. Shortest Path in Binary Matrix
994. Rotting Oranges
Highest Peak
1162. As Far from Land as Possible
286. Walls and Gates
130. Surrounded Regions
814. Shortest Path in Undirected Graph
1236. Web Crawler
417. Pacific Atlantic Water Flow
815. Bus Routes
490. The Maze
505. The Maze II
611. Knight Shortest Path [LintCode]
542. 01 Matrix
127. Word Ladder
126. Word Ladder II
133. Clone Graph
261. Graph Valid Tree
909. Snakes and Ladders
752. Open the Lock
1088. Confusing Number II
1129. Shortest Path with Alternating Colors
317. Shortest Distance from All Buildings
864. Shortest Path to Get All Keys
773. Sliding Puzzle
847. Shortest Path Visiting All Nodes
1293. Shortest Path in a Grid with Obstacles Elimination
675. Cut Off Trees for Golf Event
1345. Jump Game IV
Solution: Dijkstra
link