图与搜索
Posted futurehau
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了图与搜索相关的知识,希望对你有一定的参考价值。
主要知识点:
克隆图
拓扑排序
DFS BFS
BFS两个使用场景:图的遍历 简单图求最短路径
BFS in Graph 和BFS in Tree的主要区别就是有无环
遇到让找所有方案的题,一定是DFS,90%的DFS要么是排列,要么是组合。
Clone Graph --not bug free
方法一:递归
1 public UndirectedGraphNode cloneGraph(UndirectedGraphNode node) { 2 // write your code here 3 if (node == null) { 4 return node; 5 } 6 HashMap<UndirectedGraphNode, UndirectedGraphNode> hashMap = new HashMap<>(); 7 return help(node, hashMap); 8 } 9 10 public UndirectedGraphNode help(UndirectedGraphNode node, HashMap<UndirectedGraphNode, UndirectedGraphNode> hashMap) { 11 UndirectedGraphNode root = new UndirectedGraphNode(node.label); 12 hashMap.put(node, root); 13 for (UndirectedGraphNode neighbor : node.neighbors) { 14 if (hashMap.containsKey(neighbor)) { 15 root.neighbors.add(hashMap.get(neighbor)); 16 } else { 17 root.neighbors.add(help(neighbor, hashMap)); 18 } 19 } 20 return root; 21 }
方法二:非递归,分两步:找节点和mapping neighbors
1 public UndirectedGraphNode cloneGraph(UndirectedGraphNode node) { 2 // write your code here 3 if (node == null) { 4 return node; 5 } 6 //getNodeAndMapping 7 List<UndirectedGraphNode> nodes = new ArrayList<UndirectedGraphNode>(); 8 HashMap<UndirectedGraphNode, UndirectedGraphNode> mapping = new HashMap<>(); 9 Queue<UndirectedGraphNode> queue = new LinkedList<UndirectedGraphNode>(); 10 queue.offer(node); 11 nodes.add(node); 12 mapping.put(node, new UndirectedGraphNode(node.label)); 13 while (!queue.isEmpty()) { 14 UndirectedGraphNode cur = queue.poll(); 15 for (UndirectedGraphNode neighbor : cur.neighbors) { 16 if (mapping.containsKey(neighbor)) { 17 continue; 18 } 19 nodes.add(neighbor); 20 mapping.put(neighbor, new UndirectedGraphNode(neighbor.label)); 21 queue.offer(neighbor); 22 } 23 } 24 25 //clone neighbor 26 for (UndirectedGraphNode old : nodes) { 27 UndirectedGraphNode newNode = mapping.get(old); 28 for (UndirectedGraphNode neighbor : old.neighbors) { 29 newNode.neighbors.add(mapping.get(neighbor)); 30 } 31 } 32 return mapping.get(node); 33 }
Topological Sorting
1 public ArrayList<DirectedGraphNode> topSort(ArrayList<DirectedGraphNode> graph) { 2 // write your code here 3 Map<DirectedGraphNode, Integer> indegreeMap = new HashMap<DirectedGraphNode, Integer>(); 4 getInDegree(graph, indegreeMap); 5 Queue<DirectedGraphNode> queue = new LinkedList<DirectedGraphNode>(); 6 for (DirectedGraphNode node : graph) { 7 if (!indegreeMap.containsKey(node)) { 8 queue.offer(node); 9 } 10 } 11 ArrayList<DirectedGraphNode> result = new ArrayList<>(); 12 while (!queue.isEmpty()) { 13 DirectedGraphNode cur = queue.poll(); 14 result.add(cur); 15 for (DirectedGraphNode neighbor : cur.neighbors) { 16 int indegree = indegreeMap.get(neighbor); 17 indegreeMap.put(neighbor, indegree - 1); 18 if (indegree == 1) { 19 queue.offer(neighbor); 20 } 21 } 22 } 23 return result; 24 } 25 26 public void getInDegree(ArrayList<DirectedGraphNode> graph, 27 Map<DirectedGraphNode, Integer> indegreeMap) { 28 for (DirectedGraphNode node : graph) { 29 for (DirectedGraphNode neighbor : node.neighbors) { 30 if (!indegreeMap.containsKey(neighbor)) { 31 indegreeMap.put(neighbor, 1); 32 } else { 33 indegreeMap.put(neighbor, indegreeMap.get(neighbor) + 1); 34 } 35 } 36 } 37 }
Permutations
Given a list of numbers, return all possible permutations.You can assume that there is no duplicate numbers in the list.
public List<List<Integer>> permute(int[] nums) { // write your code here List<List<Integer>> results = new ArrayList<>(); if (nums == null || nums.length == 0) { results.add(new ArrayList<Integer>()); return results; } boolean[] used = new boolean[nums.length]; DFS(nums, results, new ArrayList<Integer>(), used); return results; } public void DFS(int[] nums, List<List<Integer>> results, List<Integer> cur, boolean[] used) { if (cur.size() == nums.length) { results.add(new ArrayList<>(cur)); return ; } for (int i = 0; i < nums.length; i++) { if (used[i]) { continue; } used[i] = true; cur.add(nums[i]); DFS(nums, results, cur, used); cur.remove(cur.size() - 1); used[i] = false; } }
Permutations II
注意不要忘了排序。
Given a list of numbers with duplicate number in it. Find all unique permutations.
1 public List<List<Integer>> permuteUnique(int[] nums) { 2 // write your code here 3 List<List<Integer>> results = new ArrayList<>(); 4 if (nums == null || nums.length == 0) { 5 results.add(new ArrayList<Integer>()); 6 return results; 7 } 8 Arrays.sort(nums); 9 boolean[] used = new boolean[nums.length]; 10 DFS(nums, results, new ArrayList<Integer>(), used); 11 return results; 12 } 13 14 public void DFS(int[] nums, List<List<Integer>> results, List<Integer> cur, boolean[] used) { 15 if (cur.size() == nums.length) { 16 results.add(new ArrayList<>(cur)); 17 return ; 18 } 19 for (int i = 0; i < nums.length; i++) { 20 if (used[i]) { 21 continue; 22 } 23 if (i > 0 && !used[i - 1] && nums[i] == nums[i - 1]) { 24 continue; 25 } 26 used[i] = true; 27 cur.add(nums[i]); 28 DFS(nums, results, cur, used); 29 cur.remove(cur.size() - 1); 30 used[i] = false; 31 } 32 }
String Permutation II
Given a list of numbers with duplicate number in it. Find all uniquepermutations.
1 public List<String> stringPermutation2(String str) { 2 // Write your code here 3 List<String> result = new ArrayList<String>(); 4 if (str == null || str.length() == 0) { 5 result.add(""); 6 return result; 7 } 8 char[] chars = str.toCharArray(); 9 Arrays.sort(chars); 10 boolean[] used = new boolean[chars.length]; 11 StringBuilder sb = new StringBuilder(); 12 DFS(chars, result, sb, used); 13 return result; 14 } 15 16 private void DFS(char[] chars, List<String> result, StringBuilder sb, boolean[] used) { 17 if (sb.length() == chars.length) { 18 result.add(sb.toString()); 19 } 20 for (int i = 0; i < chars.length; i++) { 21 if (used[i]) { 22 continue; 23 } 24 if (i != 0 && !used[i - 1] && chars[i] == chars[i - 1]) { 25 continue; 26 } 27 used[i] = true; 28 sb.append(chars[i]); 29 DFS(chars, result, sb, used); 30 used[i] = false; 31 sb.deleteCharAt(sb.length() - 1); 32 } 33 }
Subsets
Given a set of distinct integers, return all possible subsets
1 public ArrayList<ArrayList<Integer>> subsets(int[] nums) { 2 // write your code here 3 ArrayList<ArrayList<Integer>> results = new ArrayList<ArrayList<Integer>>(); 4 if (nums == null || nums.length == 0) { 5 return results; 6 } 7 Arrays.sort(nums); 8 DFS(nums, results, new ArrayList<Integer>(), 0); 9 return results; 10 } 11 12 private void DFS(int[] nums, ArrayList<ArrayList<Integer>> results, ArrayList<Integer> cur, int start) { 13 results.add(new ArrayList<Integer>(cur)); 14 for (int i = start; i < nums.length; i++) { 15 cur.add(nums[i]); 16 DFS(nums, results, cur, i + 1); 17 cur.remove(cur.size() - 1); 18 } 19 }
Subsets II
Given a list of numbers that may has duplicate numbers, return all possible subsets
1 public ArrayList<ArrayList<Integer>> subsetsWithDup(int[] nums) { 2 // write your code here 3 ArrayList<ArrayList<Integer>> results = new ArrayList<ArrayList<Integer>>(); 4 if (nums == null || nums.length == 0) { 5 return results; 6 } 7 Arrays.sort(nums); 8 DFS(nums, results, new ArrayList<Integer>(), 0); 9 return results; 10 } 11 12 private void DFS(int[] nums, ArrayList<ArrayList<Integer>> results, ArrayList<Integer> cur, int start) { 13 results.add(new ArrayList<Integer>(cur)); 14 for (int i = start; i < nums.length; i++) { 15 if (i != start && nums[i] == nums[i - 1]) { 16 continue; 17 } 18 cur.add(nums[i]); 19 DFS(nums, results, cur, i + 1); 20 cur.remove(cur.size() - 1); 21 } 22 }
k Sum II
Given n unique integers, number k (1<=k<=n) and target.
Find all possible k integers where their sum is target.
1 public ArrayList<ArrayList<Integer>> kSumII(int[] A, int k, int target) { 2 // write your code here 3 ArrayList<ArrayList<Integer>> results = new ArrayList<ArrayList<Integer>>(); 4 if (A == null || A.length == 0) { 5 results.add(new ArrayList<Integer>()); 6 return results; 7 } 8 Arrays.sort(A); 9 DFS(A, k, target, 0, results, new ArrayList<Integer>()); 10 return results; 11 } 12 13 private void DFS(int[] A, int k, int target, int start, 14 ArrayList<ArrayList<Integer>> results, ArrayList<Integer> cur) { 15 if (cur.size() > k) { 16 return ; 17 } 18 if (cur.size() == k && target == 0) { 19 results.add(new ArrayList<Integer>(cur)); 20 return ; 21 } 22 for (int i = start; i < A.length; i++) { 23 cur.add(A[i]); 24 DFS(A, k, target - A[i], i + 1, results, cur); 25 cur.remove(cur.size() - 1); 26 } 27 }
N-Queens --not bug free
1 ArrayList<ArrayList<String>> solveNQueens(int n) { 2 // write your code here 3 ArrayList<ArrayList<String>> results = new ArrayList<ArrayList<String>>(); 4 if (n <= 0) { 5 results.add(new ArrayList<String>()); 6 return results; 7 } 8 char[] helpChar = new char[n]; 9 Arrays.fill(helpChar,\'.\'); 10 boolean[] col_used = new boolean[n]; 11 boolean[] diag_pos_used = new boolean[2 * n - 1]; 12 boolean[] diag_neg_used = new boolean[2 * n - 1]; 13 help(n, results, new ArrayList<String>(), helpChar, 14 0, col_used, diag_pos_used, diag_neg_used); 15 return results; 16 } 17 18 public void help(int n, ArrayList<ArrayList<String>> results, ArrayList<String> cur, 19 char[] helpChar, int row_cur, boolean[] col_used, 20 boolean[] diag_pos_used, boolean[] diag_neg_used) { 21 if (row_cur == n) { 22 results.add(new ArrayList<String>(cur)); 23 return; 24 } 25 for (int j = 0; j < n; j++) { 26 int d1 = row_cur + j; 27 int d2 = j - row_cur + n - 1; 28 if (col_used[j] || diag_pos_used[d2] || diag_neg_used[d1]) { 29 continue; 30 } else { 31 col_used[j] = true; 32 diag_pos_used[d2] = true; 33 diag_neg_used[d1] = true; 34 helpChar[j] = \'Q\'; 35 cur.add(new String(helpChar)); 36 helpChar[j] = \'.\';//Attention 37 38 help(n, results, cur, helpChar, 39 row_cur + 1, col_used, diag_pos_used, diag_neg_used); 40 41 col_used[j] = false; 42 diag_pos_used[d2] = false; 43 diag_neg_used[d1] = false; 44 cur.remove(cur.size() - 1); 45 } 46 } 47 }
N-Queens II
Follow up for N-Queens problem.
Now, instead outputting board configurations, return the total number of distinct solutions.
1 public static int sum; 2 public int totalNQueens(int n) { 3 //write your code here 4 if (n <= 0) { 5 return 0; 6 } 7 boolean[] col_used = new boolean[n]; 8 boolean[] diag_pos_used = new boolean[2 * n]; 9 boolean[] diag_neg_used = new boolean[2 * n]; 10 sum = 0; 11 DFS(n, 0, col_used, diag_pos_used, diag_neg_used); 12 return sum; 13 } 14 15 public void DFS(int n, int row, boolean[] col_used, boolean[] diag_pos_used, boolean[] diag_neg_used) { 16 if (row == n) { 17 sum++; 18 return; 19 } 20 for (int j = 0; j < n; j++) { 21 int d1 = j - row + n - 1; 22 int d2 = j + row; 23 if (col_used[j] || diag_pos_used[d1] || diag_neg_used[d2]) { 24 continue; 25 } 26 col_used[j] = true; 27 diag_pos_used[d1] = true; 28 diag_neg_used[d2] = true; 29 DFS(n, row + 1, col_used, diag_pos_used, diag_neg_used); 30 col_used[j] = false; 31 diag_pos_used[d1] = false; 32 diag_neg_used[d2] = false; 33 } 34 }
Palindrome Partitioning
复杂度2^n,切或者不切。
Given a string s, partition s such that every substring of the partition is a palindrome.Return all possible palindrome partitioning of s.
1 List<List<String>> results = new ArrayList<List<String>>(); 2 if (s == null || s.length() == 0) { 3 results.add(new ArrayList<String>()); 4 return results; 5 } 6 int n = s.length(); 以上是关于图与搜索的主要内容,如果未能解决你的问题,请参考以下文章