6. Graph
这里收录的是真正的关于Graph data structure或者Graph Theory的题目.隐式图是一种算法/思想,不是真正关于Graph的,所以就收录在其它章节了BFS/DFS
Graph Valid Tree
这道题很好的考察了对Tree和Graph的区别的理解
还是BFS的思路更intuitive, 面试更好解释
Tree vs. Graph
树和图的区别在于是否有环
tree是parent-child relationship
Graph 是 neighbor-neighbor relation
如何判断是否是Graph: 图中存在环,同一个节点可能重复进入队列
class Solution {
/*
1.valid tree, N nodes can only have N - 1 edges
2.BFS to traversal all neighbors from a random node, check whether all nodes can be visited
3.need to build graph, Map<Integer, Set<Integer>> graph, key is node, value is set of neighbors
*/
public boolean validTree(int n, int[][] edges) {
if (edges == null || edges.length != n - 1) return false;
if (n == 1) return true;
Map<Integer, Set<Integer>> graph = buildGraph(edges);//key is node, value is set of neighbors
Set<Integer> visited = new HashSet<>();
Queue<Integer> queue = new LinkedList<>();
queue.offer(edges[0][0]);
while (!queue.isEmpty()) {
int node = queue.poll();
if (!visited.add(node)) continue;
for (int neighbor : graph.get(node)) {
queue.offer(neighbor);
}
}
return visited.size() == n;
}
private Map<Integer, Set<Integer>> buildGraph(int[][] edges) {
Map<Integer, Set<Integer>> graph = new HashMap<>();
for (int[] edge : edges) {
Set<Integer> neighbors = graph.getOrDefault(edge[0], new HashSet<>());
neighbors.add(edge[1]);
graph.put(edge[0], neighbors);
neighbors = graph.getOrDefault(edge[1], new HashSet<>());
neighbors.add(edge[0]);
graph.put(edge[1], neighbors);
}
return graph;
}
}
Course Schedule
给定一堆课程和 prerequisisites, 判断是否能完成所有课程
判断DAG是否有环的经典题型
topo sort模板题
class Solution {
public boolean canFinish(int numCourses, int[][] prerequisites) {
Map<Integer, List<Integer>> courseToNeighbors = new HashMap<>();
Map<Integer, Integer> indegrees = new HashMap<>();
for (int i = 0; i < numCourses; i++) {
indegrees.put(i, 0);
courseToNeighbors.put(i, new ArrayList<>());
}
for (int[] pre : prerequisites) {
// build graph with neighbors
courseToNeighbors.get(pre[1]).add(pre[0]);
//get indegrees of each node
indegrees.put(pre[0], indegrees.get(pre[0]) + 1);
}
Queue<Integer> queue = new LinkedList<>();
int start = 0;
Set<Integer> visited = new HashSet<>();
while (start < numCourses) {
if (indegrees.get(start) == 0) {
queue.offer(start);
visited.add(start);
}
start++;
}
while (!queue.isEmpty()) {
int cur = queue.poll();
List<Integer> neighbors = courseToNeighbors.get(cur);
for (int neighbor : neighbors) {
indegrees.put(neighbor, indegrees.get(neighbor) - 1);
if (indegrees.get(neighbor) == 0 && !visited.contains(neighbor)) {
queue.offer(neighbor);
visited.add(neighbor);
}
}
}
return visited.size() == numCourses;
}
}
这题除了用Set来记录visited node之外,还可以用list来记录visited node
这样如果需要返回任意一条路径的话就很方便
public boolean canFinish(int numCourses, int[][] prerequisites) {
Map<Integer, Integer> courseToIndegree = new HashMap<>();
Map<Integer, Set<Integer>> courseToNeighbors = new HashMap<>();
for (int i = 0; i < numCourses; i++) {
courseToIndegree.put(i, 0);
courseToNeighbors.put(i, new HashSet<Integer>());
}
for (int[] prerequisite : prerequisites) {
//get indegrees of each node
courseToIndegree.put(prerequisite[0], courseToIndegree.get(prerequisite[0]) + 1);
// build graph with neighbors
courseToNeighbors.get(prerequisite[1]).add(prerequisite[0]);
}
Queue<Integer> queue = new LinkedList<>();
for (Integer course: courseToIndegree.keySet()) {
if (courseToIndegree.get(course) == 0) {
queue.offer(course);
}
}
List<Integer> order = new ArrayList<>();
while (!queue.isEmpty()) {
Integer cur = queue.poll();
order.add(cur);
for (Integer neighbor : courseToNeighbors.get(cur)) {
courseToIndegree.put(neighbor, courseToIndegree.get(neighbor) - 1);
if (courseToIndegree.get(neighbor) == 0) {
queue.offer(neighbor);
}
}
}
return order.size() == numCourses;
}
Course Schedule II
course schedule 的follow up, 要求返回任意一条路径的结果
用一个list来记录visited node
class Solution {
public int[] findOrder(int numCourses, int[][] prerequisites) {
Map<Integer, Integer> courseToIndegree = new HashMap<>();
Map<Integer, Set<Integer>> courseToNeighbors = new HashMap<>();
for (int i = 0; i < numCourses; i++) {
courseToIndegree.put(i, 0);
courseToNeighbors.put(i, new HashSet<Integer>());
}
for (int[] prerequisite : prerequisites) {
//get indegrees of each node
courseToIndegree.put(prerequisite[0], courseToIndegree.get(prerequisite[0]) + 1);
// build graph with neighbors
courseToNeighbors.get(prerequisite[1]).add(prerequisite[0]);
}
Queue<Integer> queue = new LinkedList<>();
for (Integer course: courseToIndegree.keySet()) {
if (courseToIndegree.get(course) == 0) {
queue.offer(course);
}
}
List<Integer> order = new ArrayList<>();
while (!queue.isEmpty()) {
Integer cur = queue.poll();
order.add(cur);
for (Integer neighbor : courseToNeighbors.get(cur)) {
courseToIndegree.put(neighbor, courseToIndegree.get(neighbor) - 1);
if (courseToIndegree.get(neighbor) == 0) {
queue.offer(neighbor);
}
}
}
int[] arr = {};
if (order.size() == numCourses) {
arr = convert(order);
}
return arr;
}
private int[] convert(List<Integer> list) {
int[] arr = new int[list.size()];
for (int i = 0; i < list.size(); i++) {
arr[i] = list.get(i);
}
return arr;
}
}
Is Graph Bipartite?
graph coloring
BFS
public boolean isBipartite(int[][] graph) {
int[] groups = new int[graph.length];//groups[i] can be 0,1,2, 0 means not visited
for (int i = 0; i < graph.length; i++) {
//BFS to calculate which group node i should be
if (groups[i] != 0) continue;
Queue<Integer> queue = new LinkedList<>();
queue.offer(i);
groups[i] = 1;
while (!queue.isEmpty()) {
int cur = queue.poll();
int[] neighbors = graph[cur];
for (int neighbor : neighbors) {
if (groups[neighbor] == 0) {
queue.offer(neighbor);
groups[neighbor] = groups[cur] == 1 ? 2 : 1;
} else if (groups[neighbor] == groups[cur]) {
return false;
}
}
}
}
return true;
}
Best Meeting point
Mahattan distance
Last updated
Was this helpful?