BFS几类题:
1.图的遍历:a.层级遍历 b.由点及面 c.拓扑排序
2.简单图最短路径:
简单图:1.无向图 2.边权重一致
图的时间复杂度:
N个点,M条边,M最大是N^2,时间复杂度O(N+M),最坏是O(N^2);
矩阵是一种特殊图,R行C列矩阵,有R*C个点,R*C*2条边,所以是O(R*C);
69. Binary Tree Level Order Traversal
1 public List<List<Integer>> levelOrder(TreeNode root) { 2 // write your code here 3 if(root == null){ 4 return new ArrayList(); 5 } 6 List<List<Integer>> result = new ArrayList(); 7 Queue<TreeNode> queue = new LinkedList<TreeNode>(); 8 queue.offer(root); 9 10 while(!queue.isEmpty()){ 11 List<Integer> level = new ArrayList<>(); 12 int size = queue.size(); 13 for(int i=0;i<size;i++){ 14 TreeNode head = queue.poll(); 15 level.add(head.val); 16 if(head.left != null){ 17 queue.offer(head.left); 18 } 19 20 if(head.right != null){ 21 queue.offer(head.right); 22 } 23 } 24 result.add(level); 25 } 26 27 return result; 28 }
70. Binary Tree Level Order Traversal II
1 public List<List<Integer>> levelOrderBottom(TreeNode root) { 2 // write your code here 3 List<List<Integer>> result = new ArrayList(); 4 if(root == null){ 5 return result; 6 } 7 8 Queue<TreeNode> queue = new LinkedList<TreeNode>(); 9 queue.offer(root); 10 11 while(!queue.isEmpty()){ 12 List<Integer> level = new ArrayList(); 13 int size = queue.size(); 14 15 for(int i=0; i<size; i++){ 16 TreeNode head = queue.poll(); 17 level.add(head.val); 18 19 if(head.left != null){ 20 queue.offer(head.left); 21 } 22 23 if(head.right != null){ 24 queue.offer(head.right); 25 } 26 } 27 28 result.add(level); 29 } 30 31 Collections.reverse(result); 32 return result; 33 }
71. Binary Tree Zigzag Level Order Traversal
1 public List<List<Integer>> zigzagLevelOrder(TreeNode root) { 2 // write your code here 3 List<List<Integer>> result = new ArrayList(); 4 if(root == null){ 5 return result; 6 } 7 8 Queue<TreeNode> queue = new LinkedList<TreeNode>(); 9 queue.offer(root); 10 int count = 0; 11 while(!queue.isEmpty()){ 12 List<Integer> level = new ArrayList(); 13 int size = queue.size(); 14 15 for(int i=0; i<size; i++){ 16 TreeNode head = queue.poll(); 17 level.add(head.val); 18 19 if(head.left != null){ 20 queue.offer(head.left); 21 } 22 23 if(head.right != null){ 24 queue.offer(head.right); 25 } 26 } 27 28 if(count%2 == 1){ 29 Collections.reverse(level); 30 } 31 result.add(level); 32 count++; 33 } 34 35 return result; 36 }
7. Serialize and Deserialize Binary Tree(未AC)
178. Graph Valid Tree
valid tree条件:1.n个点n-1条边,2.n个点连通
此题重点在于如何通过给定的点和边建立邻接图Map
1 public boolean validTree(int n, int[][] edges) { 2 // write your code here 3 if(n == 0){ 4 return false; 5 } 6 7 if(edges.length != n-1){ 8 return false; 9 } 10 11 Map<Integer,Set<Integer>> neighbourMap = getNeighbourHoods(n,edges); 12 13 Queue<Integer> queue = new LinkedList<Integer>(); 14 Set<Integer> findedNodes = new HashSet<Integer>(); 15 queue.offer(0); 16 findedNodes.add(0); 17 while(!queue.isEmpty()){ 18 int node = queue.poll(); 19 Set<Integer> neighbours = neighbourMap.get(node); 20 for(Integer neighbour:neighbours){ 21 if(!findedNodes.contains(neighbour)){ 22 findedNodes.add(neighbour); 23 queue.offer(neighbour); 24 } 25 } 26 } 27 28 return (findedNodes.size()==n); 29 30 } 31 32 Map<Integer,Set<Integer>> getNeighbourHoods(int n, int[][] edges){ 33 Map<Integer, Set<Integer>> map = new HashMap<>(); 34 for(int i=0; i<n; i++){ 35 map.put(i,new HashSet<Integer>()); 36 } 37 38 for(int i=0; i<edges.length; i++){ 39 int u = edges[i][0]; 40 int v = edges[i][1]; 41 map.get(u).add(v); 42 map.get(v).add(u); 43 } 44 45 return map; 46 }
137. Clone Graph
由点及面问题:在队列初始化时,需要对记录访问点的set也初始化,非常容易因为忽略而不能AC
queue.offer(node);
nodeSet.add(node);
1 public UndirectedGraphNode cloneGraph(UndirectedGraphNode node) { 2 // write your code here 3 if(node == null){ 4 return null; 5 } 6 7 8 //get All nodes 9 List<UndirectedGraphNode> allNodes = new ArrayList<>(); 10 Queue<UndirectedGraphNode> queue = new LinkedList<UndirectedGraphNode>(); 11 Set<UndirectedGraphNode> nodeSet = new HashSet<UndirectedGraphNode>(); 12 queue.offer(node); 13 nodeSet.add(node); 14 while(!queue.isEmpty()){ 15 UndirectedGraphNode n = queue.poll(); 16 for(UndirectedGraphNode neighbor:n.neighbors){ 17 if(!nodeSet.contains(neighbor)){ 18 queue.offer(neighbor); 19 nodeSet.add(neighbor); 20 } 21 } 22 } 23 24 allNodes = new ArrayList<UndirectedGraphNode>(nodeSet); 25 26 //copy nodes and mark the new/old nodes' corresponding 27 Map<UndirectedGraphNode,UndirectedGraphNode> oldNewMap = new HashMap<>(); 28 for(UndirectedGraphNode n:allNodes){ 29 oldNewMap.put(n,new UndirectedGraphNode(n.label)); 30 } 31 32 //copy neighbors 33 for(UndirectedGraphNode n:allNodes){ 34 UndirectedGraphNode newNode = oldNewMap.get(n); 35 for(UndirectedGraphNode neighbor:n.neighbors){ 36 newNode.neighbors.add(oldNewMap.get(neighbor)); 37 } 38 } 39 40 return oldNewMap.get(node); 41 }
618. Search Graph Nodes
1 public UndirectedGraphNode searchNode(ArrayList<UndirectedGraphNode> graph, 2 Map<UndirectedGraphNode, Integer> values, 3 UndirectedGraphNode node, 4 int target) { 5 // write your code here 6 if(node == null){ 7 return null; 8 } 9 10 Queue<UndirectedGraphNode> queue = new LinkedList<UndirectedGraphNode>(); 11 Set<UndirectedGraphNode> set = new HashSet<>(); 12 13 queue.offer(node); 14 set.add(node); 15 16 while(!queue.isEmpty()){ 17 UndirectedGraphNode head = queue.poll(); 18 if(values.get(head) == target){ 19 return head; 20 } 21 22 for(UndirectedGraphNode n: head.neighbors){ 23 if(!set.contains(n)){ 24 if(values.get(n) == target){ 25 return n; 26 } 27 queue.offer(n); 28 set.add(n); 29 } 30 } 31 } 32 33 return null; 34 }
127. Topological Sorting
拓扑排序基础题,一定要掌握思路
1 public ArrayList<DirectedGraphNode> topSort(ArrayList<DirectedGraphNode> graph) { 2 // write your code here 3 ArrayList<DirectedGraphNode> result = new ArrayList<>(); 4 if(graph == null || graph.size()==0){ 5 return result; 6 } 7 8 Map<DirectedGraphNode,Integer> map = new HashMap<>(); 9 //统计入度 10 for(DirectedGraphNode node: graph){ 11 for(DirectedGraphNode n: node.neighbors){ 12 Integer exist = map.get(n); 13 if(exist == null){ 14 map.put(n,1); 15 }else{ 16 map.put(n,exist+1); 17 } 18 } 19 } 20 21 //取出入度为0的点初始化队列和拓扑结果 22 Queue<DirectedGraphNode> queue = new LinkedList<>(); 23 for(DirectedGraphNode node : graph){ 24 if(!map.containsKey(node)){ 25 queue.offer(node); 26 result.add(node); 27 } 28 } 29 30 //BFS 更新入度,按入度为0的顺序进行拓扑排序 31 while(!queue.isEmpty()){ 32 DirectedGraphNode head = queue.poll(); 33 for(DirectedGraphNode neighbor: head.neighbors){ 34 map.put(neighbor,map.get(neighbor)-1); 35 if(map.get(neighbor) == 0){ 36 queue.offer(neighbor); 37 result.add(neighbor); 38 } 39 } 40 } 41 42 return result; 43 }
615. Course Schedule
这题其实不用开Hash去存,由于给定的条件特殊,其实可以通过同长度数组对应位置去存储(可参考标准答案)
1 public boolean canFinish(int numCourses, int[][] prerequisites) { 2 // write your code here 3 4 //构建邻接Map,加统计入度 5 Map<Integer,ArrayList<Integer>> map = new HashMap<>(); 6 Map<Integer,Integer> degreeMap = new HashMap(); 7 8 for(int i=0; i<numCourses; i++){ 9 map.put(i,new ArrayList<Integer>()); 10 } 11 12 //注意审题,这题反了对结果没有影响,但如果需要输出序列则不能AC 13 for(int i=0; i<prerequisites.length; i++){ 14 map.get(prerequisites[i][1]).add(prerequisites[i][0]); 15 if(!degreeMap.containsKey(prerequisites[i][0])){ 16 degreeMap.put(prerequisites[i][0],1); 17 }else{ 18 degreeMap.put(prerequisites[i][0],degreeMap.get(prerequisites[i][0])+1); 19 } 20 } 21 22 23 //拓扑排序 24 int count =0; 25 Queue<Integer> queue = new LinkedList<>(); 26 for(int i=0; i<numCourses; i++){ 27 if(!degreeMap.containsKey(i)){ 28 queue.offer(i); 29 count++; 30 } 31 } 32 33 while(!queue.isEmpty()){ 34 Integer course = queue.poll(); 35 for(Integer nextCourse: map.get(course)){ 36 degreeMap.put(nextCourse,degreeMap.get(nextCourse)-1); 37 if(degreeMap.get(nextCourse)==0){ 38 queue.offer(nextCourse); 39 count++; 40 } 41 } 42 } 43 44 return (count==numCourses); 45 }
616. Course Schedule II
1 public int[] findOrder(int numCourses, int[][] prerequisites) { 2 // write your code here 3 int[] result = new int[numCourses]; 4 //构建邻接Map,加统计入度 5 Map<Integer,ArrayList<Integer>> map = new HashMap<>(); 6 Map<Integer,Integer> degreeMap = new HashMap(); 7 8 for(int i=0; i<numCourses; i++){ 9 map.put(i,new ArrayList<Integer>()); 10 } 11 12 for(int i=0; i<prerequisites.length; i++){ 13 map.get(prerequisites[i][1]).add(prerequisites[i][0]); 14 if(!degreeMap.containsKey(prerequisites[i][0])){ 15 degreeMap.put(prerequisites[i][0],1); 16 }else{ 17 degreeMap.put(prerequisites[i][0],degreeMap.get(prerequisites[i][0])+1); 18 } 19 } 20 21 22 //拓扑排序 23 int count = 0; 24 Queue<Integer> queue = new LinkedList<>(); 25 for(int i=0; i<numCourses; i++){ 26 if(!degreeMap.containsKey(i)){ 27 queue.offer(i); 28 result[count] = i; 29 count++; 30 } 31 } 32 33 while(!queue.isEmpty()){ 34 Integer course = queue.poll(); 35 for(Integer nextCourse: map.get(course)){ 36 degreeMap.put(nextCourse,degreeMap.get(nextCourse)-1); 37 if(degreeMap.get(nextCourse)==0){ 38 queue.offer(nextCourse); 39 result[count] = nextCourse; 40 count++; 41 } 42 } 43 } 44 45 if(count == numCourses){ 46 return result; 47 } 48 49 return new int[0]; 50 }
605. Sequence Reconstruction
这题要注意细节判断,思路简单,但不容易AC
1 public boolean sequenceReconstruction(int[] org, int[][] seqs) { 2 // write your code here 3 //判断seqs是否有超过org范围的数字 4 //构建入度和邻接表 5 //BFS,判断是否只能又一个拓扑排序,且数字是否一一对应 6 7 Map<Integer, Integer> degreeMap = new HashMap<>(); 8 Map<Integer, List<Integer>> adjacentMap = new HashMap<>(); 9 10 int min = Integer.MAX_VALUE; 11 int max = Integer.MIN_VALUE; 12 for(int num : org){ 13 // adjacentMap.put(num, new ArrayList<>()); 14 min = num<min? num:min; 15 max = num>max? num:max; 16 } 17 18 19 for(int[] seq: seqs){ 20 if(seq.length>0 && (seq[0]>max || seq[0]<min)){ 21 return false; 22 } 23 if(seq.length>0 && !adjacentMap.containsKey(seq[0])){ 24 adjacentMap.put(seq[0],new ArrayList()); 25 } 26 for(int i =1; i<seq.length; i++){ 27 if(seq[i]>max || seq[i]<min){ 28 return false; 29 } 30 if(degreeMap.containsKey(seq[i])){ 31 degreeMap.put(seq[i],degreeMap.get(seq[i])+1); 32 }else{ 33 degreeMap.put(seq[i],1); 34 } 35 if(!adjacentMap.containsKey(seq[i-1])){ 36 adjacentMap.put(seq[i-1],new ArrayList()); 37 } 38 if(!adjacentMap.containsKey(seq[i])){ 39 adjacentMap.put(seq[i],new ArrayList()); 40 } 41 adjacentMap.get(seq[i-1]).add(seq[i]); 42 } 43 } 44 45 46 Queue<Integer> queue = new LinkedList<>(); 47 for(int num: org){ 48 if(!adjacentMap.containsKey(num)){ 49 return false; 50 } 51 if(!degreeMap.containsKey(num)){ 52 queue.offer(num); 53 } 54 } 55 56 int index =0; 57 while(queue.size()==1){ 58 Integer head = queue.poll(); 59 if(head != org[index]){ 60 return false; 61 } 62 index++; 63 for(int neighbor: adjacentMap.get(head)){ 64 degreeMap.put(neighbor,degreeMap.get(neighbor)-1); 65 if(degreeMap.get(neighbor)==0){ 66 queue.offer(neighbor); 67 } 68 } 69 } 70 71 return (index == org.length); 72 }
433. Number of Islands
1 class Coordinate{ 2 int x; 3 int y; 4 public Coordinate(int x,int y){ 5 this.x = x; 6 this.y = y; 7 } 8 } 9 10 public class Solution { 11 /** 12 * @param grid: a boolean 2D matrix 13 * @return: an integer 14 */ 15 16 int[] directX = {0,1,0,-1}; 17 int[] directY = {1,0,-1,0}; 18 public int numIslands(boolean[][] grid) { 19 // write your code here 20 if(grid == null ||grid.length==0){ 21 return 0; 22 } 23 24 int r = grid.length; 25 int c = grid[0].length; 26 27 if(r==0 || c==0){ 28 return 0; 29 } 30 31 int count =0; 32 for(int i =0; i<r; i++){ 33 for(int j =0; j<c; j++){ 34 if(grid[i][j]){ 35 BFS(grid,new Coordinate(i,j)); 36 count++; 37 } 38 } 39 } 40 41 return count; 42 } 43 44 public void BFS(boolean[][] grid,Coordinate center){ 45 Queue<Coordinate> queue = new LinkedList<>(); 46 queue.offer(center); 47 grid[center.x][center.y]=false; 48 49 while(!queue.isEmpty()){ 50 Coordinate head = queue.poll(); 51 for(int i =0;i<4; i++){ 52 Coordinate point = new Coordinate(head.x+directX[i],head.y+directY[i]); 53 if(!isInMatrix(point,grid)){ 54 continue; 55 } 56 if(grid[point.x][point.y]){ 57 queue.offer(point); 58 grid[point.x][point.y] = false; 59 } 60 } 61 } 62 } 63 64 public boolean isInMatrix(Coordinate point, boolean[][] grid){ 65 int r = grid.length; 66 int c = grid[0].length; 67 return(point.x>=0 && point.x<r && point.y>=0 && point.y<c); 68 } 69 70 }
598. Zombie in Matrix
1 class Coordinate{ 2 int x; 3 int y; 4 public Coordinate(int x, int y){ 5 this.x = x; 6 this.y = y; 7 } 8 } 9 10 public class Solution { 11 /** 12 * @param grid: a 2D integer grid 13 * @return: an integer 14 */ 15 16 private static final int ZOMBIE = 1; 17 private static final int PEOPLE = 0; 18 private static final int WALL = 2; 19 20 int[] directX = {0,1,0,-1}; 21 int[] directY = {1,0,-1,0}; 22 public int zombie(int[][] grid) { 23 // write your code here 24 25 if(grid == null || grid.length ==0 || grid[0].length ==0){ 26 return 0; 27 } 28 29 int r = grid.length; 30 int c = grid[0].length; 31 Queue<Coordinate> queue = new LinkedList<>(); 32 33 int people = 0; 34 for(int i=0; i<r; i++) 35 for(int j=0; j<c; j++){ 36 if(grid[i][j] == ZOMBIE){ 37 queue.offer(new Coordinate(i,j)); 38 } 39 if(grid[i][j] == PEOPLE){ 40 people++; 41 } 42 } 43 44 if(people == 0){ 45 return 0; 46 } 47 //BFS 48 int day = 0; 49 while(!queue.isEmpty()){ 50 day++; 51 int size = queue.size(); 52 for(int i = 0; i<size; i++){ 53 Coordinate center = queue.poll(); 54 for(int j=0; j<4; j++){ 55 Coordinate next = new Coordinate(center.x+directX[j],center.y+directY[j]); 56 if(!isInMatrix(next,grid)){ 57 continue; 58 } 59 60 if(grid[next.x][next.y] == PEOPLE){ 61 grid[next.x][next.y] = ZOMBIE; 62 queue.offer(next); 63 people--; 64 if(people ==0){ 65 return day; 66 } 67 } 68 } 69 } 70 } 71 72 73 return -1; 74 75 76 } 77 78 public boolean isInMatrix(Coordinate point, int[][]grid){ 79 int r = grid.length; 80 int c = grid[0].length; 81 82 return(point.x>=0 && point.x<r && point.y>=0 && point.y<c); 83 } 84 }
611. Knight Shortest Path
1 /** 2 * Definition for a point. 3 * class Point { 4 * int x; 5 * int y; 6 * Point() { x = 0; y = 0; } 7 * Point(int a, int b) { x = a; y = b; } 8 * } 9 */ 10 11 public class Solution { 12 /** 13 * @param grid: a chessboard included 0 (false) and 1 (true) 14 * @param source: a point 15 * @param destination: a point 16 * @return: the shortest path 17 */ 18 19 int[] directX = {1,1,-1,-1,2,2,-2,-2}; 20 int[] directY = {2,-2,2,-2,1,-1,1,-1}; 21 public int shortestPath(boolean[][] grid, Point source, Point destination) { 22 // write your code here 23 if(grid == null || grid.length==0 || grid[0].length==0){ 24 return -1; 25 } 26 27 if(source.x == destination.x && source.y==destination.y){ 28 return 0; 29 } 30 31 Queue<Point> queue = new LinkedList<>(); 32 queue.offer(source); 33 34 int step = 0; 35 while(!queue.isEmpty()){ 36 step++; 37 int size = queue.size(); 38 for(int i =0; i<size; i++){ 39 Point center = queue.poll(); 40 for(int j=0; j<8; j++){ 41 Point next = new Point(center.x+directX[j],center.y+directY[j]); 42 if(!isInMatrix(next,grid)){ 43 continue; 44 } 45 46 if(next.x == destination.x && next.y == destination.y){ 47 return step; 48 } 49 50 if(!grid[next.x][next.y]){ 51 queue.offer(next); 52 grid[next.x][next.y] = true; 53 } 54 } 55 } 56 } 57 58 return -1; 59 } 60 61 public boolean isInMatrix(Point point, boolean[][]grid){ 62 int r = grid.length; 63 int c = grid[0].length; 64 65 return(point.x>=0 && point.x<r && point.y>=0 && point.y<c); 66 } 67 }
431. Connected Component in Undirected Graph
1 public List<List<Integer>> connectedSet(List<UndirectedGraphNode> nodes) { 2 // write your code here 3 if(nodes == null || nodes.size() ==0){ 4 return new ArrayList<>(); 5 } 6 7 List<List<Integer>> result = new ArrayList<>(); 8 Queue<UndirectedGraphNode> queue = new LinkedList<>(); 9 Set<UndirectedGraphNode> visit = new HashSet<>(); 10 11 12 for(UndirectedGraphNode node: nodes){ 13 if(!visit.contains(node)){ 14 List<Integer> list = new ArrayList<>(); 15 list.add(node.label); 16 queue.offer(node); 17 visit.add(node); 18 19 while(!queue.isEmpty()){ 20 UndirectedGraphNode head = queue.poll(); 21 for(UndirectedGraphNode neighbor: head.neighbors){ 22 if(!visit.contains(neighbor)){ 23 list.add(neighbor.label); 24 queue.offer(neighbor); 25 visit.add(neighbor); 26 } 27 } 28 } 29 30 Collections.sort(list); 31 result.add(list); 32 33 } 34 } 35 36 return result; 37 38 }
120. Word Ladder
1 public int ladderLength(String start, String end, Set<String> dict) { 2 // write your code here 3 if(start == null || end ==null || dict == null){ 4 return 0; 5 } 6 7 if(start.equals(end)){ 8 return 1; 9 } 10 11 dict.add(end); 12 dict.add(start); 13 14 int steps = 1; 15 Queue<String> queue = new LinkedList<>(); 16 Set<String> visited = new HashSet<>(); 17 queue.offer(start); 18 visited.add(start); 19 20 while(!queue.isEmpty()){ 21 steps++; 22 int size = queue.size(); 23 for(int i =0; i<size; i++){ 24 String word = queue.poll(); 25 for(String next: getNextWords(word,dict)){ 26 if(next.equals(end)){ 27 return steps; 28 } 29 30 if(!visited.contains(next)){ 31 visited.add(next); 32 queue.offer(next); 33 } 34 } 35 } 36 } 37 38 return 0; 39 } 40 public ArrayList<String> getNextWords(String word, Set<String> dict){ 41 ArrayList<String> result = new ArrayList<>(); 42 for(int i=0; i< word.length(); i++){ 43 for(char c = 'a'; c<='z'; c++){ 44 if(word.charAt(i) == c){ 45 continue; 46 } 47 48 String replacedWord = getReplacedWorld(word,i,c); 49 if(dict.contains(replacedWord)){ 50 result.add(replacedWord); 51 } 52 } 53 } 54 55 return result; 56 } 57 58 public String getReplacedWorld(String word,int index, char c){ 59 char[] chars = word.toCharArray(); 60 chars[index] = c; 61 return new String(chars); 62 }