leetcode图相关基础题目
左神图模板
作用: 熟悉这套模板,在作图相关题目时自己写一个接口将题目所给的数据结构转化为图对象,再使用该数据结构完成算法。
// 结点
class Node {
int value; // 结点的编号或值,不同题目灵活应变
int in; // 入度
int out; // 出度
ArrayList<Node> nexts; // 从该结点出发连向的其他结点
ArrayList<Edge> edges; // 该结点出所形成的边
public Node (int value) {
this.value = value;
in = 0;
out = 0;
nexts = new ArrayList<>();
edges = new ArrayList<>();
}
}
// 边
class Edge {
int weight; // 边的权重,根据题目灵活变动
Node from; // 这条边的起始结点
Node to; // 这条边的终止结点
public Edge(int weight, Node from, Node to) {
this.weight = weight;
this.from = from;
this.to = to;
}
}
// 图
class Graph {
HashsMap<Integer, Node> nodes; // 图中所有的结点
HashSet<Edge> edges; // 图中所有的边
public Graph() {
nodes = new HashMap<>();
edges = new HashSet<>();
}
}
leetcode 863. 二叉树中所有距离为 K 的结点
给定一个二叉树(具有根结点 root), 一个目标结点 target ,和一个整数值 k 。
返回到目标结点 target 距离为 k 的所有结点的值的列表。 答案可以以 任何顺序 返回。
思路: 使用图的宽度优先遍历(BFS)。先将题目中的数据结构转化为熟悉的图结构,找到目标结点,从目标节点开始出发对图进行宽度优先遍历,在遍历过程中需要记录当是在第几层,这里采用了二叉树层序遍历的技巧,使用curEnd记录当前层的最后一个结点,nextEnd记录下一层的最后一个结点,以此来判断目前是在哪一层,当在第k层时,将该层的节点记录到结果集中。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public List<Integer> distanceK(TreeNode root, TreeNode target, int k) {
List<Integer> res = new ArrayList<>();
Graph graph = new Graph();
createGraph(root, graph);
// BFS
Queue<Node> queue = new LinkedList<>();
Set<Node> set = new HashSet<>();
Node node = graph.nodes.get(target.val);
if (node == null) return res;
queue.add(node);
set.add(node);
int step = 0;
Node curEnd = node;
Node nextEnd = null;
while (!queue.isEmpty()) {
Node cur = queue.poll();
if (step == k) res.add(cur.value);
for (Node next : cur.nexts) {
if (!set.contains(next)) {
queue.add(next);
set.add(next);
nextEnd = next;
}
}
if (cur == curEnd) {
step++;
curEnd = nextEnd;
nextEnd = null;
}
}
return res;
}
public List<Integer> distanceK2(TreeNode root, TreeNode target, int k) {
List<Integer> res = new ArrayList<>();
Graph graph = new Graph();
createGraph(root, graph);
// DFS 未成功
Stack<Node> stack = new Stack<>();
Set<Node> set = new HashSet<>();
Node node = graph.nodes.get(target.val);
stack.add(node);
set.add(node);
while (!stack.isEmpty()) {
Node cur = stack.pop();
// res.add(cur.value);
for (Node next : cur.nexts) {
if (!set.contains(next)) {
stack.add(cur);
stack.add(next);
set.add(next);
res.add(next.value);
break;
}
}
}
return res;
}
// 将二叉树转化为图
public void createGraph(TreeNode root, Graph graph) {
if (root == null) return;
Integer from = root.val;
if (!graph.nodes.containsKey(from)) {
graph.nodes.put(from, new Node(from));
}
Node fromNode = graph.nodes.get(from);
if (root.left != null) {
int toLeft = root.left.val;
if (!graph.nodes.containsKey(toLeft)) {
graph.nodes.put(toLeft, new Node(toLeft));
}
Node toLeftNode = graph.nodes.get(toLeft);
Edge leftEdge1 = new Edge(0, fromNode, toLeftNode);
Edge leftEdge2 = new Edge(0, toLeftNode, fromNode);
fromNode.nexts.add(toLeftNode);
toLeftNode.nexts.add(fromNode);
fromNode.out++;
fromNode.in++;
toLeftNode.out++;
toLeftNode.in++;
fromNode.edges.add(leftEdge1);
toLeftNode.edges.add(leftEdge2);
graph.edges.add(leftEdge1);
graph.edges.add(leftEdge2);
}
if (root.right != null) {
int toRight = root.right.val;
if (!graph.nodes.containsKey(toRight)) {
graph.nodes.put(toRight, new Node(toRight));
}
Node toRightNode = graph.nodes.get(toRight);
Edge rightEdge1 = new Edge(0, fromNode, toRightNode);
Edge rightEdge2 = new Edge(0, toRightNode, fromNode);
fromNode.nexts.add(toRightNode);
toRightNode.nexts.add(fromNode);
fromNode.out++;
fromNode.in++;
toRightNode.out++;
toRightNode.in++;
fromNode.edges.add(rightEdge1);
toRightNode.edges.add(rightEdge2);
graph.edges.add(rightEdge1);
graph.edges.add(rightEdge2);
}
createGraph(root.left, graph);
createGraph(root.right, graph);
}
}
class Node {
int value;
int in;
int out;
ArrayList<Node> nexts;
ArrayList<Edge> edges;
int step;
public Node(int value) {
this.value = value;
in = 0;
out = 0;
step = 0;
nexts = new ArrayList<>();
edges = new ArrayList<>();
}
public void setStep(int s) {
step = s;
}
}
class Edge {
int weight;
Node from;
Node to;
public Edge(int weight, Node from, Node to) {
this.weight = weight;
this.from = from;
this.to = to;
}
}
class Graph {
HashMap<Integer, Node> nodes;
HashSet<Edge> edges;
public Graph() {
nodes = new HashMap<>();
edges = new HashSet<>();
}
}
leetcode 207. 课程表
你这个学期必须选修 numCourses 门课程,记为 0 到 numCourses - 1 。
在选修某些课程之前需要一些先修课程。 先修课程按数组 prerequisites 给出,其中 prerequisites[i] = [ai, bi] ,表示如果要学习课程 ai 则 必须 先学习课程 bi 。
例如,先修课程对 [0, 1] 表示:想要学习课程 0 ,你需要先完成课程 1 。
请你判断是否可能完成所有课程的学习?如果可以,返回 true ;否则,返回 false 。
class Solution {
public boolean canFinish<