📅  最后修改于: 2023-12-03 15:36:03.235000             🧑  作者: Mango
在二叉树中,如果要打印两个任意节点之间的路径,有以下几个问题需要解决:
本套装解决了以上三个问题,并提供了多种实现方案。
在二叉树中找到两个节点之间的路径可以使用回溯(递归)方法。具体实现如下:
public boolean findPath(TreeNode root, int n, List<Integer> path) {
if (root == null) {
return false;
}
path.add(root.val);
if (root.val == n) {
return true;
}
if (findPath(root.left, n, path) || findPath(root.right, n, path)) {
return true;
}
path.remove(path.size() - 1);
return false;
}
其中,root
为当前节点,n
为目标节点的值,path
为存储路径节点值的列表。函数返回 true
表示找到目标节点,否则返回 false
。
找到路径后,我们需要将节点值打印出来。具体实现如下:
public void printPath(List<Integer> path) {
for (int i = 0; i < path.size(); i++) {
System.out.print(path.get(i));
if (i != path.size() - 1) {
System.out.print("->");
}
}
System.out.println();
}
其中,path
为存储路径节点值的列表。打印完路径后,还需要将 path
清空,以存储下一条路径。
打印所有节点之间的路径可以使用回溯(递归)方法。具体实现如下:
public void printAllPaths(TreeNode root, List<Integer> path, List<List<Integer>> paths) {
if (root == null) {
return;
}
path.add(root.val);
if (root.left == null && root.right == null) {
paths.add(new ArrayList<>(path));
} else {
printAllPaths(root.left, path, paths);
printAllPaths(root.right, path, paths);
}
path.remove(path.size() - 1);
}
其中,root
为当前节点,path
为存储路径节点值的列表,paths
为存储所有节点之间路径的列表。当 root
为叶子节点时,将 path
加入 paths
提前打印出来。
本套装提供了三种实现方案,分别为:
public void findAndPrintPath(TreeNode root, int n1, int n2) {
List<Integer> path = new ArrayList<>();
List<List<Integer>> paths = new ArrayList<>();
findAndPrintPathHelper(root, n1, n2, path, paths);
}
private void findAndPrintPathHelper(TreeNode root, int n1, int n2, List<Integer> path, List<List<Integer>> paths) {
if (!findPath(root, n1, path) || !findPath(root, n2, path)) {
return;
}
if (!path.contains(n1) || !path.contains(n2)) {
return;
}
int i = path.indexOf(n1);
int j = path.indexOf(n2);
if (i > j) {
int temp = i;
i = j;
j = temp;
}
List<Integer> subpath = path.subList(i, j + 1);
printPath(subpath);
path.clear();
paths.clear();
printAllPaths(root, path, paths);
for (List<Integer> p : paths) {
if (p.contains(n1) && p.contains(n2)) {
printPath(p);
}
}
}
public void findAndPrintPath(TreeNode root, int n1, int n2) {
List<Integer> path = new ArrayList<>();
List<List<Integer>> paths = new ArrayList<>();
findAndPrintPathHelper(root, n1, n2, path, paths);
}
private void findAndPrintPathHelper(TreeNode root, int n1, int n2, List<Integer> path, List<List<Integer>> paths) {
Stack<TreeNode> stack = new Stack<>();
TreeNode curr = root, prev = null;
while (curr != null || !stack.isEmpty()) {
while (curr != null) {
stack.push(curr);
path.add(curr.val);
curr = curr.left;
}
curr = stack.peek();
if (curr.right == null || curr.right == prev) {
if (curr.val == n1 || curr.val == n2) {
if (!findPath(root, n1, path) || !findPath(root, n2, path)) {
return;
}
if (!path.contains(n1) || !path.contains(n2)) {
return;
}
int i = path.indexOf(n1);
int j = path.indexOf(n2);
if (i > j) {
int temp = i;
i = j;
j = temp;
}
List<Integer> subpath = path.subList(i, j + 1);
printPath(subpath);
path.clear();
paths.clear();
printAllPaths(root, path, paths);
for (List<Integer> p : paths) {
if (p.contains(n1) && p.contains(n2)) {
printPath(p);
}
}
return;
}
stack.pop();
path.remove(path.size() - 1);
prev = curr;
curr = null;
} else {
curr = curr.right;
}
}
}
def find_and_print_path(root, n1, n2):
stack = []
curr = root
prev = None
path = []
paths = []
while curr or stack:
while curr:
stack.append(curr)
path.append(curr.val)
curr = curr.left
curr = stack[-1]
if not curr.right or curr.right == prev:
if curr.val == n1 or curr.val == n2:
if not find_path(root, n1, path) or not find_path(root, n2, path):
return
if n1 not in path or n2 not in path:
return
i = path.index(n1)
j = path.index(n2)
if i > j:
i, j = j, i
subpath = path[i:j + 1]
print_path(subpath)
path.clear()
paths.clear()
print_all_paths(root, path, paths)
for p in paths:
if n1 in p and n2 in p:
print_path(p)
return
stack.pop()
path.pop()
prev = curr
curr = None
else:
curr = curr.right
本套装提供了多种实现方案,递归实现代码简洁,但需要额外的存储空间;迭代实现代码稍微复杂,但不需要额外的存储空间,且效率更高。根据实际需求选择实现方案即可。