[关闭]
@ysongzybl 2015-05-26T04:11:44.000000Z 字数 6945 阅读 815

Summary: Problems solved by BFS I: Graph

interview


BFS For Graph

  1. /**
  2. * BFS Version Graph Traversal Template:
  3. */
  4. BFS(V){
  5. let Q be a queue
  6. Q.push(V)
  7. label V as visted
  8. while(!Q.empty()){
  9. u = Q.pop()
  10. for all edges from u to w
  11. if w is not visited
  12. enqueue w
  13. mark w visited
  14. }
  1. /**
  2. * BFS Version Topological Sort Template:
  3. */
  4. let L be an empty list
  5. let S be the set of nodes without incoming edges
  6. while( !S.empty()){
  7. remove a node n from S
  8. append n to L
  9. foreach node m with edge e from n to m
  10. remove e from graph
  11. if m has no incoming edge
  12. insert m to S
  13. }
  14. if still there are some incoming edges for some nodes
  15. return // the graph has a cycle
  16. return L

1. Surrounded Regions

Given a 2D board containing 'X' and 'O', capture all regions surrounded by 'X'.
A region is captured by flipping all 'O's into 'X's in that surrounded region.

Example :
X X X X
X O O X
X X O X
X O X X
After running your function, the board should be:
X X X X
X X X X
X X X X
X O X X

Idea:
- BFSearch 'O's on the boards, replace 'O's with 'Y's
- For the remaining 'O's, replace with 'X's
- Recover 'Y's with 'O's

Also can be solved with DFS, but large data test case will throw a stack overflow error

  1. class Pos{
  2. int x, y;
  3. Pos(int i, int j){ x = i; y = j;}
  4. }
  5. int dx[] = {1,-1,0,0};
  6. int dy[] = {0,0,1,-1};
  7. public void bfs(char [][] board, int i, int j){
  8. if(board[i][j] !='O') return;
  9. int m = board.length;
  10. int n = board[0].length;
  11. Queue<Pos> Q = new LinkedList<Pos>();
  12. Q.offer(new Pos(i, j));
  13. while(!Q.isEmpty()){
  14. Pos cur = Q.poll();
  15. if(cur.x < 0|| cur.y<0 || cur.x==m || cur.y ==n) continue;
  16. if(board[cur.x][cur.y]!='O') continue;
  17. board[cur.x][cur.y] = 'Y';
  18. for(int k=0; k<4; k++){
  19. Pos neighbor = new Pos(cur.x+dx[k], cur.y+dy[k]);
  20. Q.offer(neighbor);
  21. }
  22. }
  23. }
  24. public void solve(char[][] board) {
  25. int m = board.length;
  26. if(m==0) return;
  27. int n= board[0].length;
  28. for(int row=0; row<m; row++){ // left/right column
  29. bfs(board, row, 0);
  30. bfs(board, row, n-1);
  31. }
  32. for(int col=0; col<n; col++){ // top/bottom row
  33. bfs(board, 0, col);
  34. bfs(board, m-1, col);
  35. }
  36. // check inner area, fill 'O's with 'X's
  37. for(int i=1; i<m-1; i++){
  38. for(int j=1; j<n-1; j++){
  39. if(board[i][j]=='O') board[i][j]='X';
  40. }
  41. }
  42. // recover 'Y's back to 'O's
  43. for(int i=0; i<m; i++){
  44. for(int j=0;j<n; j++){
  45. if(board[i][j]=='Y') board[i][j]='O';
  46. }
  47. }
  48. }

2. Number of Islands

Given a 2d grid map of '1's (land) and '0's (water), count the number of islands.
An island is surrounded by water and is formed by connecting adjacent lands horizontally or vertically.
You may assume all four edges of the grid are all surrounded by water.

Example 1:
11110
11010
11000
00000
Answer: 1

Example 2:
11000
11000
00100
00011
Answer: 3

Idea:
BFSearch from a position of '1' (update count at the same time)
Mark visited '1' as '0'

  1. class Pos{
  2. int x, y;
  3. Pos(int i, int j){x=i; y=j;}
  4. }
  5. int dx[] = {1,-1,0,0};
  6. int dy[] = {0,0,1,-1};
  7. public void bfs(char[][] grid, int i, int j){
  8. if(grid[i][j] != '1') return; // water, return
  9. int m = grid.length;
  10. int n = grid[0].length;
  11. Queue<Pos> Q= new LinkedList<Pos>();
  12. Q.offer(new Pos(i, j));
  13. while(!Q.isEmpty()){
  14. Pos cur = Q.poll();
  15. if(cur.x <0 || cur.y<0|| cur.x==m || cur.y==n) continue;
  16. if(grid[cur.x][cur.y]!='1') continue;
  17. grid[cur.x][cur.y] = '0'; // mark visited land as water
  18. for(int k=0; k<4; k++){
  19. Pos neighbor = new Pos(cur.x+dx[k], cur.y+dy[k]);
  20. Q.offer(neighbor);
  21. }
  22. }
  23. }
  24. public int numIslands(char[][] grid) {
  25. int m = grid.length;
  26. if(m==0) return 0;
  27. int n = grid[0].length;
  28. int count = 0;
  29. for(int i=0; i<m; i++){
  30. for(int j=0; j<n; j++){
  31. if(grid[i][j]=='1'){
  32. count++;
  33. bfs(grid, i, j);
  34. }
  35. }
  36. }
  37. return count;
  38. }

3. Course Schedule I/II

There are a total of n courses you have to take, labeled from 0 to n - 1.
Some courses may have prerequisites, for example to take course 0 you have to first take course 1, which is expressed as a pair: [0,1]
Given the total number of courses and a list of prerequisite pairs, is it possible for you to finish all courses?

Example:
2, [[1,0]]
There are a total of 2 courses to take. To take course 1 you should have finished course 0. So it is possible.
2, [[1,0],[0,1]]
There are a total of 2 courses to take. To take course 1 you should have finished course 0, and to take course 0 you should
also have finished course 1. So it is impossible.

Idea: topological sort
- There is an implicit fact here: the courses numbers are from 0,,n1. We can represent n graph nodes using integers from 0n1.
- Use hashmap to represent the graph: map: key is the node id i, value is the list of of nodes' id's: so that node i has outgoing edges to these nodes.
- Use array incoming[] to record the number of incoming edges for each node: incoming[i] = j means node i has j incoming edges.

  1. public boolean canFinish(int numCourses, int[][] prerequisites) {
  2. int n = prerequisites.length;
  3. if(n==0) return true;
  4. HashMap<Integer, ArrayList<Integer>> pre_posts = new HashMap<Integer, ArrayList<Integer>>();
  5. int incoming[] = new int [numCourses]; // mistake: numCousrses is not necessarily equal to n!
  6. for(int [] pair : prerequisites){
  7. int pre = pair[1];
  8. int post = pair[0];
  9. incoming[post]++;
  10. if(!pre_posts.containsKey(pre)){
  11. pre_posts.put(pre, new ArrayList<Integer>());
  12. }
  13. pre_posts.get(pre).add(post);
  14. }
  15. // find nodes without incoming edges
  16. Queue<Integer> Q = new LinkedList<Integer>();
  17. for(int i=0; i<numCourses; i++){
  18. if(incoming[i]==0) Q.offer(i);
  19. }
  20. while(!Q.isEmpty()){
  21. Integer pre = Q.poll();
  22. // important! must check key existance
  23. if(!pre_posts.containsKey(pre)) continue;
  24. for(Integer post : pre_posts.get(pre)){
  25. incoming[post]--;
  26. if(incoming[post]==0){
  27. Q.offer(post);
  28. }
  29. }
  30. }
  31. for(int i: incoming){
  32. if(i>0) return false;
  33. }
  34. return true;
  35. }

4. Clone Graph

Clone an undirected graph. Each node in the graph contains a label and a list of its neighbors.

  1. /**
  2. * Definition for undirected graph.
  3. * class UndirectedGraphNode {
  4. * int label;
  5. * List<UndirectedGraphNode> neighbors;
  6. * UndirectedGraphNode(int x) { label = x; neighbors = new ArrayList<UndirectedGraphNode>(); }
  7. * };
  8. */
  9. //BFS version solution
  10. public UndirectedGraphNode cloneGraph(UndirectedGraphNode node) {
  11. if(node == null) return null;
  12. HashMap<Integer, UndirectedGraphNode> cloned = new HashMap<Integer, UndirectedGraphNode>();
  13. Queue<UndirectedGraphNode> Q = new LinkedList<UndirectedGraphNode>();
  14. Q.offer(node);
  15. cloned.put(node.label, new UndirectedGraphNode(node.label));
  16. while(!Q.isEmpty()){
  17. UndirectedGraphNode cur = Q.poll();
  18. for(UndirectedGraphNode neighbor : cur.neighbors){
  19. if(!cloned.containsKey(neighbor.label)){
  20. cloned.put(neighbor.label, new UndirectedGraphNode(neighbor.label));
  21. Q.offer(neighbor);
  22. }
  23. cloned.get(cur.label).neighbors.add(cloned.get(neighbor.label));
  24. }
  25. }
  26. return cloned.get(node.label);
  27. }

5. Word Ladder

Given two words (beginWord and endWord), and a dictionary, find the length of shortest transformation sequence from beginWord to endWord, such that:
Only one letter can be changed at a time
Each intermediate word must exist in the dictionary

Example,
Given:
start = "hit"
end = "cog"
dict = ["hot","dot","dog","lot","log"]
As one shortest transformation is "hit" -> "hot" -> "dot" -> "dog" -> "cog",
return its length 5.

  1. public ArrayList<String> getOneEditWords(String word){
  2. ArrayList<String> neighbors = new ArrayList<String>();
  3. char wd[] = word.toCharArray();
  4. for(int i=0; i<wd.length; i++){
  5. char origin = wd[i];
  6. for(char c = 'a'; c<='z'; c++){
  7. if(wd[i] != c) {
  8. wd[i] = c;
  9. neighbors.add(new String(wd));
  10. wd[i] = origin;
  11. }
  12. }
  13. }
  14. return neighbors;
  15. }
  16. public int ladderLength(String beginWord, String endWord, Set<String> wordDict) {
  17. if(wordDict.size()==0) return 0;
  18. Queue<String> Q = new LinkedList<String>();
  19. Q.offer(beginWord);
  20. HashSet<String> visited = new HashSet<String>();
  21. visited.add(beginWord);
  22. int len = 1;
  23. int curr_level = 1, next_level=0;
  24. while(!Q.isEmpty()){
  25. String cur = Q.poll();
  26. curr_level--;
  27. for(String next : getOneEditWords(cur)){
  28. if(next.equals(endWord)){ return len+1;}
  29. if(wordDict.contains(next)) {
  30. if(!visited.contains(next)){
  31. Q.offer(next);
  32. visited.add(next);
  33. next_level++;
  34. }
  35. }
  36. }
  37. if(curr_level==0){
  38. curr_level = next_level;
  39. next_level = 0;
  40. len++;
  41. }
  42. }
  43. return 0;
  44. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注