18、二叉树的镜像
索引root树的结点: root.left root.right
class Solution {
public TreeNode mirrorTree(TreeNode root) {
if(root == null) return null;
TreeNode tmp = root.left;
root.left = mirrorTree(root.right);
root.right = mirrorTree(tmp);
return root;
}
}
public TreeNode mirrorTree(TreeNode root) {
if (root == null) {
return null;
}
TreeNode leftRoot = mirrorTree(root.right);
TreeNode rightRoot = mirrorTree(root.left);
root.left = leftRoot;
root.right = rightRoot;
return root;
}
38、二叉树的深度
二叉树的遍历方式
先序遍历:先根节点->遍历左子树->遍历右子树
中序遍历:遍历左子树->根节点->遍历右子树
后序遍历:遍历左子树->遍历右子树->根节点
树的后序遍历 / 深度优先搜索往往利用 递归 或 栈 实现,本文使用递归实现
递归、关键在于找到递归结束条件
class Solution {
public int maxDepth(TreeNode root) {
if(root == null) return 0;
return Math.max(maxDepth(root.left), maxDepth(root.right)) + 1;
}
}
树的层序遍历 / 广度优先搜索往往利用 队列 实现。
62、二叉搜索树的第K个子节点
二叉搜索树的特点:左结点的值<根结点的值<右结点的值。
按照中序遍历的顺序对一棵二叉搜索树进行遍历,那么得到的遍历序列就是递增排序的。
因此,只要用中序遍历的顺序遍历一棵二叉搜索树,就很容易找出它的第k大结点。
中序遍历
// 打印中序遍历
void dfs(TreeNode root) {
if(root == null) return;
dfs(root.left); // 左
System.out.println(root.val); // 根
dfs(root.right); // 右
}
int count=0, res=0;//形参k不能随着dfs的迭代而不断变化,为了记录迭代进程和结果,引入类变量count和res。
public int kthLargest(TreeNode root, int k) {
this.count=k;//利用形参值k对类变量count进行初始化
dfs(root);//这里不要引入形参k,dfs中直接使用的是初始值为k的类变量count
return res;
}
public void dfs(TreeNode root){
if(root==null) return;//当root为空,直接返回
dfs(root.right);
if(--count==0){//先--,若 k = 0,代表当前节点为第 k 大的节点
res = root.val;
return;//这里的return可以避免之后的无效迭代dfs(root.left);
}
dfs(root.left);
}
39、平衡二叉树
此树的深度 等于 左子树的深度 与 右子树的深度 中的 最大值 +1
class Solution {
public boolean isBalanced(TreeNode root) {
if (root == null) return true;
return Math.abs(depth(root.left) - depth(root.right)) <= 1 && isBalanced(root.left) && isBalanced(root.right);//当前子树 当前左子树 当前右子树
}
private int depth(TreeNode root) {
if (root == null) return 0;
return Math.max(depth(root.left), depth(root.right)) + 1;
}
}
58、对称的二叉树
/*思路:首先根节点以及其左右子树,左子树的左子树和右子树的右子树相同
* 左子树的右子树和右子树的左子树相同即可,采用递归
* 非递归也可,采用栈或队列存取各级子树根节点
* 1.只要pRoot.left和pRoot.right是否对称即可
2.左右节点的值相等且对称子树left.left, right.right ;left.rigth,right.left也对称
*/
public class Solution {
boolean isSymmetrical(TreeNode pRoot)
{
if(pRoot == null){
return true;
}
return comRoot(pRoot.left, pRoot.right);
}
private boolean comRoot(TreeNode left, TreeNode right) {
// TODO Auto-generated method stub
if(left == null) return right==null;
if(right == null) return false;
if(left.val != right.val) return false;
return comRoot(left.right, right.left) && comRoot(left.left, right.right);
}
}
57、二叉树的下一个节点
思路:三种情况:(1)若给定结点有右子树,则下一个结点是它右子树中最左边的结点
(2)若该结点没有右子树,并且是父节点的左结点,则下一个结点就是他的父节点
(3)若该结点没有右子树,并且是父节点的右结点,则应该沿着父节点向上,直到找到的结点是一个左结点。则下一个结点是该左结点的父节点
*/
public class Solution {
TreeLinkNode GetNext(TreeLinkNode node)
{
if(node==null) return null;
if(node.right!=null){ //如果有右子树,则找右子树的最左节点
node = node.right;
while(node.left!=null) node = node.left;
return node;
}
while(node.next!=null){ //没右子树,则找第一个当前节点是父节点的左孩子的节点
if(node.next.left==node) return node.next; //当前节点的 父节点的 左孩子 是其本身,就返回当前结点的父节点
node = node.next; //next就是父节点
}
return null; //退到了根节点仍没找到,则返回null
}
}