文章目录
- 前言
- 二叉树前中后序遍历
- 反转二叉树
- 二叉树最大最小深度
- 对称二叉树
- 判断是否是平衡二叉树
- 构造最大二叉树
- 前序遍历打印二叉树
- 二叉树层次遍历
- 二叉树中和为某一值的路径
- 总结
前言
二叉树基础内容拾遗,使用递归解题三部曲:
- 找整个递归的终止条件: 递归应该在什么时候结束?
- 找返回值: 应该给上一级返回什么信息?
- 本级递归应该做什么:在这一级递归中应该完成什么任务?
提示:以下是本篇文章正文内容,下面案例可供参考
二叉树前中后序遍历
public void preorderTraversal(TreeNode root) {
if (root != null) {
System.out.print(root.val + " ");
preorderTraversal(root.left);
preorderTraversal(root.right);
}
}
public void inorderTraversal(TreeNode root) {
if (root != null) {
inorderTraversal(root.left);
System.out.print(root.val + " ");
inorderTraversal(root.right);
}
}
public void postorderTraversal(TreeNode root) {
if (root != null) {
postorderTraversal(root.left);
postorderTraversal(root.right);
System.out.print(root.val + " ");
}
}
反转二叉树
- 递归实现
public TreeNode invertTree(TreeNode node) {
if (node == null) {return null;}
TreeNode temp = node.left;
node.left = node.right;
node.right = temp;
invertTree(node.left);
invertTree(node.right);
return node;
}
- 非递归队列实现
public TreeNode invertTree(TreeNode root) {
if (root == null) {return null;}
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()) {
TreeNode node = queue.poll();
TreeNode left = node.left;
node.left = node.right;
node.right = left;
if (node.left != null) {
queue.offer(node.left);
}
if (node.right != null) {
queue.offer(node.right);
}
}
return root;
}
二叉树最大最小深度
public static int treeMaxDepth(TreeNode curr) {
if (curr != null) {
int left = treeMaxDepth(curr.left);
int right = treeMaxDepth(curr.right);
return left > right ? left + 1 : right + 1;
}
return 0;
}
public static int treeMinDepth(TreeNode root) {
TreeNode curr = root;
if (curr == null) return 0;
if (curr.left == null && curr.right == null) return 1;
int min_depth = Integer.MAX_VALUE;
if (curr.left != null) {
min_depth = Math.min(treeMinDepth(curr.left), min_depth);
}
if (curr.right != null) {
min_depth = Math.min(treeMinDepth(curr.right), min_depth);
}
return min_depth + 1;
}
对称二叉树
public boolean isSymmetric(TreeNode root) {
return isMirror(root, root);
}
public boolean isMirror(TreeNode left, TreeNode right) {
if (left == null && right == null) return true;
if (left == null || right == null) return false;
return (left.val == right.val) && isMirror(left.left, right.right) && isMirror(left.right, right.left);
}
判断是否是平衡二叉树
平衡二叉树即左右两棵子树高度差不大于1的二叉树。
条件:
它的左子树是平衡二叉树,
它的右子树是平衡二叉树,
它的左右子树的高度差不大于1。
在我们眼里,这颗二叉树就3个节点:root、left、right
class Solution2 {
public boolean isBalanced(TreeNode root) {
return height(root) >= 0;
}
private int height(TreeNode root) {
if (root == null)
return 0;
int lh = height(root.left), rh = height(root.right);
if (lh >= 0 && rh >= 0 && Math.abs(lh - rh) <= 1) {
return Math.max(lh, rh) + 1;
} else {
return -1;
}
}
构造最大二叉树
https://leetcode-cn.com/problems/maximum-binary-tree/
给定一个不含重复元素的整数数组 nums 。一个以此数组直接递归构建的 最大二叉树 定义如下:
二叉树的根是数组 nums 中的最大元素。
左子树是通过数组中 最大值左边部分 递归构造出的最大二叉树。
右子树是通过数组中 最大值右边部分 递归构造出的最大二叉树。
返回有给定数组 nums 构建的 最大二叉树 。
一次递归做了什么?
找当前范围为[l,r]的数组中的最大值作为root节点,然后将数组划分成[l,bond-1]和[bond+1,r]两段,并分别构造成root的左右两棵子最大二叉树
public class _654_最大二叉树 {
public static void main(String[] args) {
int[] arr = new int[]{3, 2, 1, 6, 0, 5};
TreeNode treeNode = new _654_最大二叉树().constructMaximumBinaryTree(arr);
ArrayList<Integer> list = TreeNode.printFromTopToBottom(treeNode);
System.out.println(list);
}
public TreeNode constructMaximumBinaryTree(int[] nums) {
return maxTree(nums, 0, nums.length - 1);
}
public TreeNode maxTree(int[] nums, int l, int r) {
if (l > r) return null;
int maxIndex = findMaxIndex(nums, l, r);
TreeNode root = new TreeNode(nums[maxIndex]);
root.left = maxTree(nums, l, maxIndex - 1);
root.right = maxTree(nums, maxIndex + 1, r);
return root;
}
public int findMaxIndex(int[] nums, int l, int r) {
int max = Integer.MIN_VALUE, maxIndex = l;
for (int i = l; i <= r; i++) {
if (max < nums[i]) {
max = nums[i];
maxIndex = i;
}
}
return maxIndex;
}
}
前序遍历打印二叉树
public static ArrayList<Integer> printFromTopToBottom(TreeNode root) {
ArrayList<Integer> arrayList = new ArrayList<Integer>();
if (root==null){
return arrayList;
}
Queue<TreeNode> queue = new LinkedList<TreeNode>();
queue.offer(root);
while (!queue.isEmpty()){
TreeNode node= queue.poll();
arrayList.add(node.val);
if (node.left!=null){
queue.offer(node.left);
}
if (node.right!=null){
queue.offer(node.right);
}
}
return arrayList;
}
二叉树层次遍历
示例:
二叉树:[3,9,20,null,null,15,7],
3
/ \
9 20
/ \
15 7
返回其层序遍历结果:
[
[3],
[9,20],
[15,7]
]
链接:https://leetcode-cn.com/problems/binary-tree-level-order-traversal
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> ret = new ArrayList<>();
if (root == null) {
return ret;
}
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()) {
List<Integer> list = new ArrayList<>();
int currentLevelSize = queue.size();
for (int i = 1; i <= currentLevelSize; ++i) {
TreeNode node = queue.poll();
list.add(node.val);
if (node.left != null) {
queue.offer(node.left);
}
if (node.right != null) {
queue.offer(node.right);
}
}
ret.add(list);
}
return ret;
}
二叉树中和为某一值的路径
参考:https://www.cnblogs.com/lishanlei/p/10707709.html
由于路径是从根节点出发到叶子节点的,因此我们需要首先遍历根节点,只有前序遍历是首先访问根节点的。
当访问某一个节点时,我们不知道前面经过了哪些节点,所以我们需要将经过的路径上的节点保存下来,每访问一个节点,我们需要把当前节点添加到路径中去。
在遍历下一个节点前,先要回到当前节点的父节点,在去其他节点,当回到父节点时,之前遍历的那个节点已经不在当前路径中了,所以需要删除之前在路径中的那个节点。
public List<ArrayList<Integer>> FindPath(TreeNode root, int target) {
List<ArrayList<Integer>> listAll = new ArrayList<>();
List<Integer> list = new ArrayList<>();
return SeekPath(listAll, list, root, target);
}
private List<ArrayList<Integer>> SeekPath(List<ArrayList<Integer>> listAll, List<Integer> list, TreeNode root, int target) {
if (root == null) return listAll;
list.add(root.val);
target -= root.val;
if (target == 0 && root.left == null && root.right == null) {
listAll.add(new ArrayList<>(list));
}
SeekPath(listAll, list, root.left, target);
SeekPath(listAll, list, root.right, target);
list.remove(list.size() - 1);
return listAll;
}
总结
未完待续
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)