算法思想-二叉树


一、可出算法

在这里插入图片描述


二、解决

1. 二叉树的深度

递归

public int TreeDepth(TreeNode root) {
  if(root == null)
      return 0;
  int leftDepth = TreeDepth(root.left);  // 左子树深度
  int rightDepth = TreeDepth(root.ight);  // 右子树深度
  int depth = 1 + max(leftDepth, rightDepth);  // 当前节点的深度
  return depth;
}
 

// 简写:
public int TreeDepth(TreeNode root) {
  if(root == null)
      return 0;
  return Math.max(TreeDepth(root.left), TreeDepth(root.right)) + 1;
}

层序遍历

public int TreeDepth(TreeNode root) {
    if(root == null) return 0;
    Queue<TreeNode> queue = new LinkedList<>();
    queue.add(root);
    int res = 0;
    while(!queue.isEmpty()){
        Queue<TreeNode> temp = new LinkedList<>(); // 需要一个临时队列存储
        for(TreeNode node:queue){
            if(node.left!=null) temp.add(node.left);
            if(node.right!=null) temp.add(node.right);
        }
        queue = temp; // 赋值
        res++;
    }
    return res;
}

2. 按之字形顺序打印二叉树

  • 栈,先进后出;设置标识位,记录从左往右还是从右往左
public ArrayList<ArrayList<Integer> > Print(TreeNode pRoot) {
   ArrayList<ArrayList<Integer>> res = new ArrayList<>();
   if(pRoot == null) return res;
   boolean flag = true;
   Stack<TreeNode> stack1 = new Stack<>();
   Stack<TreeNode> stack2 = new Stack<>();
   stack1.add(pRoot);
   while(!stack1.isEmpty() || !stack2.isEmpty()) {
       ArrayList<Integer> line = new ArrayList<>();
       if(flag) {
           while(!stack1.isEmpty()) {
               TreeNode pop = stack1.pop();
               line.add(pop.val);
               if(pop.left != null) stack2.add(pop.left);
               if(pop.right != null) stack2.add(pop.right);
           }
       } else {
           while(!stack2.isEmpty()) {
               TreeNode pop = stack2.pop();
               line.add(pop.val);
               if(pop.right != null) stack1.add(pop.right);
               if(pop.left != null) stack1.add(pop.left);
           }
       }
       res.add(line);
       flag = !flag;
   }
   return res;
}

3. 二叉搜索树的第k小个节点

  • 二叉搜索树:中序遍历(左根右)是从小到大的排序序列
  • 延伸:若要得到二叉搜索树的第K大节点,将“左根右”的顺序换成“右根左”即可

递归

int res = -1, k = -1;
public int KthNode (TreeNode proot, int k) {
  if(proot == null) return -1;
  this.k = k;
  dfs(proot);
  return res;
}

void dfs(TreeNode root) {
  if(root == null || k <= 0) return; //当root为空或者已经找到了res时,直接返回
  dfs(root.left);
  if(--k == 0){ //先--,再判断
      res = root.val;
      return; //这里的 return 可以避免之后的无效迭代dfs(root.left);
  }
  dfs(root.right);  
}

迭代

public int KthNode (TreeNode proot, int k) {
	if(proot == null) return -1;
    Stack<TreeNode> stack = new Stack<>();
    stack.push(proot);
    TreeNode cur = proot;
    while(!stack.isEmpty()) {
    	// 先找到左子树的最左子节点
        while(cur.left != null) {
            stack.push(cur.left);
            cur = cur.left;
        }
        k--;
        TreeNode temp = stack.pop();
        if(0 == k) return temp.val;
        if(temp.right != null) {
            stack.push(temp.right);
            cur = temp.right;
        }
    }
    return -1;
}

4. 重建二叉树

递归

public TreeNode reConstructBinaryTree(int [] pre,int [] vin) {
    if(pre == null || pre.length <=0 || vin == null || vin.length <=0 || pre.length != vin.length)
        return null;
    int len = pre.length;
    return buildTree(pre, vin, 0, len-1, 0, len-1);
}

private TreeNode buildTree(int[] pre, int[] in, int preLeft, int preRight, int inLeft, int inRight) {
    if(preLeft > preRight || inLeft > inRight) return null;
    int preRoot = pre[preLeft];
    TreeNode root = new TreeNode(preRoot);
    int index;
    for(index = inLeft; index < inRight; index++) {
        if(preRoot == in[index]) break;
    }
    int len = index - inLeft;
    root.left = buildTree(pre, in, preLeft + 1, preLeft + len, inLeft, inLeft + len -1);
    root.right = buildTree(pre, in, preLeft + len + 1, preRight, inLeft + len + 1, inRight);
    return root;
}

迭代

public TreeNode reConstructBinaryTree(int [] pre,int [] vin) {
   if(pre == null || pre.length <=0 || vin == null || vin.length <=0 || pre.length != vin.length)
       return null;
   int len = pre.length;
   TreeNode root = new TreeNode(pre[0]);
   LinkedList<TreeNode> stack = new LinkedList<>();
   stack.push(root);
   int index = 0;
   for(int i = 1; i < len; i++) {
       int preVal = pre[i];
       TreeNode node = stack.peek();
       if(node.val != vin[index]) {
           node.left = new TreeNode(preVal);
           stack.push(node.left);
       } else {
           while(!stack.isEmpty() && stack.peek().val == vin[index]) {
               node = stack.pop();
               index++;
           }
           node.right = new TreeNode(preVal);
           stack.push(node.right);
       }
   }
   return root;
}

5、树的子结构

递归

public boolean HasSubtree(TreeNode root1,TreeNode root2) {
    if(root1 == null || root2 == null) return false;
    return check(root1, root2) || HasSubtree(root1.left, root2) || HasSubtree(root1.right, root2);
}

private boolean check(TreeNode root1, TreeNode root2) {
    if(root2 == null) return true;
    if(root1 == null || root1.val != root2.val) return false;
    return check(root1.left, root2.left) && check(root1.right, root2.right);
}

6、二叉树的镜像

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值