二叉树相关问题编程实现
1、求二叉树的深度(java中基本数据类型的封装类是不可变类(值不可变),如果需要修改,jvm会新建一个对象,导致在被调函数中对值的修改传不回调用函数,因此不能实现指针的功能。)
private static int getDepth(TreeNode root) {
if(root == null) {
return 0;
}
if(root.left == null && root.right == null) {
return 1;
}
int lDepth = getDepth(root.left);
int rDepth = getDepth(root.right);
return lDepth > rDepth ? lDepth + 1 : rDepth + 1;
}
2、在二叉树中找出所有从根结点到某个结点路径中结点之和为指定值得路径(因为需要保存路径,所以要用一个辅助栈,回溯法,并使用两个变量一个表示当前的和,一个表示目标和,因为只涉及比较操作,而不需要返回值,所以可以使用基本数据类型做参数,递归先根访问二叉树)
package AboutBinaryTree;
import java.util.ArrayList;
import java.util.Stack;
import AboutBinaryTree.BinaryTree;
import AboutBinaryTree.TreeNode;
public class GetPathToSum {
public static void main(String[] args) {
TreeNode ten = new TreeNode(10), five = new TreeNode(5), twelve = new TreeNode(12),
four = new TreeNode(4), seven = new TreeNode(7);
ten.left = five; ten.right = twelve; five.left = four; five.right = seven;
BinaryTree bt = new BinaryTree(ten);
ArrayList<ArrayList<Integer>> result = new ArrayList<>();
Stack<TreeNode> path = new Stack<>();
boolean exist = getPathToSum(bt.root, 0, 15, path, result);
if(exist)
for(ArrayList<Integer> tmp : result) {
for(int x : tmp)
System.out.print(x + " ");
System.out.println();
}
else
System.out.println("Doesn't exist!");
}
private static boolean getPathToSum(TreeNode root, int currentSum, int expectedSum,
Stack<TreeNode> path, ArrayList<ArrayList<Integer>> result) {
if(root == null)
return false;
path.push(root);
currentSum += root.value;
// boolean isLeaf = root.left == null && root.right == null;
if(currentSum == expectedSum) {
ArrayList<Integer> tmp = new ArrayList<>();
for(TreeNode n : path)
tmp.add(n.value);
result.add(tmp);
return true;
}
boolean left = false, right = false;
if(root.left != null)
left = getPathToSum(root.left, currentSum, expectedSum, path, result);
if(root.right != null)
right = getPathToSum(root.right, currentSum, expectedSum, path, result);
path.pop();
currentSum -= root.value;
return left || right;
}
}
3、取得到指定结点的路径(辅助栈,回溯法,递归先根访问二叉树)
package AboutBinaryTree;
import java.util.Stack;
import java.util.ArrayList;
import AboutBinaryTree.BinaryTree;
import AboutBinaryTree.TreeNode;
public class GetPathToNode {
public static void main(String[] args) {
TreeNode ten = new TreeNode(10), five = new TreeNode(5), twelve = new TreeNode(12),
four = new TreeNode(4), seven = new TreeNode(7);
ten.left = five; ten.right = twelve; five.left = four; five.right = seven;
BinaryTree bt = new BinaryTree(ten);
TreeNode tarNode = four;
ArrayList<Integer> result = new ArrayList<>();
Stack<TreeNode> path = new Stack<>();
boolean exist = getPathToSum(bt.root, tarNode, path, result);
if(exist) {
for(Integer x : result)
System.out.print(x + " ");
System.out.println();
}
else
System.out.println("Doesn't exist!");
}
private static boolean getPathToSum(TreeNode root, TreeNode targetNode,
Stack<TreeNode> path, ArrayList<Integer> result) {
if(root == null || targetNode == null)
return false;
path.push(root);
// boolean isLeaf = root.left == null && root.right == null;
if(root == targetNode) {
for(TreeNode n : path)
System.out.print(n.value + " ");
return true;
}
boolean left = false, right = false;
left = getPathToSum(root.left, targetNode, path, result);
right = getPathToSum(root.right, targetNode, path, result);
path.pop();
return left || right;
}
}
4、树2是否是树1的子结构
private static boolean hasSubTree(TreeNode bt1, TreeNode bt2) {
if(bt1 == null)
return false;
if(bt2 == null)
return true;
if(bt1.value == bt2.value)
return doseTree1hasTree2(bt1, bt2);
return hasSubTree(bt1.left, bt2) || hasSubTree(bt1.right, bt2);
}
private static boolean doseTree1hasTree2(TreeNode bt1, TreeNode bt2) {
if(bt2 == null)
return true;
if(bt1 == null)
return false;
if(bt1.value != bt2.value)
return false; //把这句放在这里可以避免空指针异常,相当于是先进行指针是否为空的检查
return doseTree1hasTree2(bt1.left, bt2.left) && doseTree1hasTree2(bt1.right, bt2.right);
}
5、求最深层的结点
思路一:不需要返回路径,所以不用回溯,只需要先根访问二叉树,因为只涉及比较操作,所以可以使用基本数据类型的参数记录当前叶子的层数,当为叶子结点时,需要将该叶子结点的层数与最大层数(这里使用一个全局变量)比较,如果大,则需要更新最大层数,并且把结果列表清空,再加入这个更深的叶子节点,如果等于最大层数,只需要将当前叶子结点加入到结果列表中即可。
思路二:先计算出树的层数,然后采用层次遍历二叉树的方法遍历二叉树,这里使用两个变量分别记录当前层的结点数目和下一层的结点数目,设置一个累加器表示已经打印的层数,如果当前层输出完了,累加器累加到下一层,如果是倒数第二层,那么队列中的元素便是最深一层结点,此时推出循环。
package AboutBinaryTree;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;
public class GetDeepestNodes {
public static int level_max = Integer.MIN_VALUE;
public static void main(String[] args) {
TreeNode ten = new TreeNode(10), five = new TreeNode(5), twelve = new TreeNode(12),
four = new TreeNode(4), seven = new TreeNode(7), six = new TreeNode(6),
eight = new TreeNode(8), nine = new TreeNode(9), eleven = new TreeNode(11);
ten.left = five; ten.right = twelve; five.left = four; five.right = seven; four.left = six;
four.right = eight; seven.right = nine; nine.right = eleven;
BinaryTree bt1 = new BinaryTree(ten);
// ArrayList<TreeNode> result = getDeepestNodes1(bt1.root);
ArrayList<TreeNode> result = new ArrayList<>();
getDeepestNodes2(bt1.root, result, 1);
for(TreeNode n : result)
System.out.print(n.value + " ");
}
private static void getDeepestNodes2(TreeNode root, ArrayList<TreeNode> result, int currLevel) {
if(root == null)
return;
boolean isLeaf = root.left == null && root.right == null;
if(isLeaf) {
if(currLevel > level_max) {
level_max = currLevel;
result.clear();
result.add(root);
}
else
if(currLevel == level_max)
result.add(root);
}
currLevel ++;
getDeepestNodes2(root.left, result, currLevel);
getDeepestNodes2(root.right, result, currLevel);
}
private static ArrayList<TreeNode> getDeepestNodes1(TreeNode root) {
ArrayList<TreeNode> r = new ArrayList<>();
if(root == null)
return r;
Queue<TreeNode> q = new LinkedList<>();
q.offer(root);
int currNodes = 1, nextNodes = 0;
int level = getDepth(root), currLevel = 0;
TreeNode p;
while(!q.isEmpty()) {
p = q.poll();
currNodes--;
if(p.left != null) {
q.offer(p.left);
nextNodes++;
}
if(p.right != null) {
q.offer(p.right);
nextNodes++;
}
if(currNodes == 0) {
currNodes = nextNodes;
nextNodes = 0;
currLevel++;
if(currLevel == level - 1)
break;
}
}
while(!q.isEmpty())
r.add(q.poll());
return r;
}
private static int getDepth(TreeNode root) {
if(root == null) {
return 0;
}
if(root.left == null && root.right == null) {
return 1;
}
int lDepth = getDepth(root.left);
int rDepth = getDepth(root.right);
return lDepth > rDepth ? lDepth + 1 : rDepth + 1;
}
}