二叉树进阶问题

二叉树进阶问题,第1张

二叉树进阶问题

二叉树进阶问题
  • 1.判断一颗树是否是完全二叉树
  • 2.二叉树遍历
  • 3.从前序与中序遍历序列构造二叉树
  • 4.从中序与后续遍历序列构造二叉树
  • 5.二叉树的最近公共祖先
  • 6.根据二叉树创建字符串
  • 7.二叉搜索树与双向链表

1.判断一颗树是否是完全二叉树

1.判断一棵树是否是完全二叉树:
(1)完全二叉树该树中若存在右子树则必然存在左子树
(2)完全二叉树的节点编号必须和满二叉树一一对应(你有的节点必须和满二叉树节点编号相同)。
(3)对于完全二叉树来说一共存在三种节点:
A.度为2的节点有N个
B.度为1的节点最多有一个(恰好就是左树的那个一个节点)
C.度为0的节点有N个
(4)判断方法:

package bin_tree.leetcode;

import java.util.linkedList;
import java.util.Queue;

public class IsCompleteTree {
    public boolean isCompleteTree(TreeNode root) {
        if (root == null) {
            return true;
        }
        // 层序遍历判断二叉树
        Queue queue = new linkedList<>();
        queue.offer(root);
        // 引入标志位,来区分当前遍历过程处在第一还是第二阶段
        boolean isSecondStep = false;
        while (!queue.isEmpty()) {
            TreeNode cur = queue.poll();
            if (!isSecondStep) {
                // 此时处在第一阶段
                if (cur.left != null && cur.right != null) {
                    // 当前cur左右子树全部都存在
                    queue.offer(cur.left);
                    queue.offer(cur.right);
                }else if (cur.left == null && cur.right != null) {
                    // 此时只有右树没有左树,反例
                    return false;
                }else if (cur.left != null) {
                    // 只有左树没有右树,此时cur是碰到的第一个只有左树的节点
                    // 切换状态
                    isSecondStep = true;
                    queue.offer(cur.left);
                }else {
                    // 此时左树和右树全部为空,cur第一个碰到的叶子节点
                    isSecondStep = true;
                }
            }else {
                // 此时处在第二阶段,第二阶段中的所有节点不可能有子树
                // 有一个反例就false
                if (cur.left != null || cur.right != null) {
                    return false;
                }
            }
        }
        // 遍历全部结束,没有找到反例
        return true;
    }
}
2.二叉树遍历

2.二叉树遍历

根据题意画出该二叉树的结构:

代码实现:

package bin_tree.NewCoder;

import java.util.Scanner;

// 根据先序遍历结果还原二叉树,输出中序遍历结果
public class KY11 {
    private static class TreeNode {
        char val;
        TreeNode left;
        TreeNode right;
        public TreeNode(char val) {
            this.val = val;
        }
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        // 获取用户多组输入
        while (scanner.hasNext()) {
            // 字符串形式的先序二叉树结果
            String line = scanner.next();
            // str -> TreeNode
            TreeNode root = build(line);
            // 中序遍历二叉树,按照格式打印结点值
            inOrder(root);
            // 每个结果占一行
            System.out.println();
        }
    }

    private static void inOrder(TreeNode root) {
        if (root == null)
            return;
        inOrder(root.left);
        System.out.print(root.val +" ");
        inOrder(root.right);
    }

    // 根据先序遍历结果字符串还原二叉树,返回构建后二叉树的根节点
    private static TreeNode build(String line) {
        return preOrderBuild(line);
    }
    // abc##de#g##f###
    // str -> char
    // 当前处理到哪个字符了
    static int index = 0;
    private static TreeNode preOrderBuild(String line) {
        char c = line.charAt(index);
        if (c == '#') {
            return null;
        }
        TreeNode root = new TreeNode(c);
        index ++;
        root.left = preOrderBuild(line);
        index ++;
        root.right = preOrderBuild(line);
        return root;
    }
}

运行截图:

3.从前序与中序遍历序列构造二叉树

3.从二叉树与中序遍历序列构造二叉树

1.代码实现:

package bin_tree.leetcode;


public class Num105 {
    // 当前处理到前序遍历的哪个位置
    int index = 0;
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        return buildTreeInternal(preorder,inorder,0,inorder.length);
    }

    
    public TreeNode buildTreeInternal(int[] preOrder,int[] inOrder,int left,int right) {
        if(left >= right) {
            return null;
        }
        if (index >= preOrder.length) {
            return null;
        }
        TreeNode root = new TreeNode(preOrder[index]);
        index ++;
        int pos = find(inOrder,left,right,root.val);
        root.left = buildTreeInternal(preOrder,inOrder,left,pos);
        root.right = buildTreeInternal(preOrder,inOrder,pos + 1,right);
        return root;
    }
    
    private int find(int[] inOrder, int left, int right, int val) {
        for (int i = left; i < right; i++) {
            if (inOrder[i] == val) {
                return i;
            }
        }
        return -1;
    }
}

4.从中序与后续遍历序列构造二叉树

4.从中序与后续遍历序列构造二叉树

package bin_tree.leetcode;

import java.util.HashMap;
import java.util.Map;


public class Num106 {
    // 存储中序遍历的对应的值和索引
    Map map = new HashMap<>();
    public TreeNode buildTree(int[] inorder, int[] postorder) {
        // 将后序遍历结果反转
        int[] preOrder = reverse(inorder,postorder);
        return buildTreeInternal(preOrder,inorder,0,inorder.length);
    }
    int index = 0;
    public TreeNode buildTreeInternal(int[] preOrder,int[] inOrder,int left,int right) {
        if(left >= right) {
            return null;
        }
        if (index >= preOrder.length) {
            return null;
        }
        TreeNode root = new TreeNode(preOrder[index]);
        index ++;
        int pos = map.get(root.val);
        root.right = buildTreeInternal(preOrder,inOrder,pos + 1,right);
        root.left = buildTreeInternal(preOrder,inOrder,left,pos);
        return root;
    }

    private int[] reverse(int[] inorder,int[] postorder) {
        int[] ret = new int[postorder.length];
        for (int i = 0; i < ret.length; i++) {
            ret[i] = postorder[ret.length - 1 - i];
        }
        for (int i = 0; i < inorder.length; i++) {
            map.put(inorder[i],i);
        }
        return ret;
    }
}

5.二叉树的最近公共祖先

5.二叉树的最近公共祖先

package bin_tree.leetcode;


public class Num236 {
    TreeNode lca;
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if (root == null) {
            return null;
        }
        // 从根节点出发进行后序遍历,找到lca(p和q出现在三个位置的两个)
        find(root,p,q);
        return lca;
    }
    // 在以root为根节点的二叉树中,是否能同时找到p和q
    private boolean find(TreeNode root, TreeNode p, TreeNode q) {
        if (root == null) {
            return false;
        }
        int left = find(root.left,p,q) ? 1 : 0;
        int right = find(root.right,p,q) ? 1 : 0;
        int mid = (root == p || root == q) ? 1 : 0;
        if (left + right + mid == 2) {
            lca = root;
            return true;
        }
        return (left + right + mid) > 0;
    }
}

6.根据二叉树创建字符串

6.根据二叉树创建字符串

package bin_tree.leetcode;


public class Num606 {
    StringBuilder sb = new StringBuilder();
    // "1(2(4))(3)"
    public String tree2str(TreeNode root) {
        if (root == null) {
            return "";
        }
        preOrder(root);
        return sb.toString();
    }
    private void preOrder(TreeNode root) {
        if (root == null) {
            return;
        }
        // "1(2(4))(3)"
        sb.append(root.val);
        if (root.left != null) {
            sb.append("(");
            // 先序遍历左树
            preOrder(root.left);
            sb.append(")");
        }else {
            // 左空,判断右树是否为空
            if (root.right != null) {
                sb.append("()");
            }
        }
        if (root.right != null) {
            sb.append("(");
            preOrder(root.right);
            sb.append(")");
        }
    }
}

7.二叉搜索树与双向链表

package bin_tree.NewCoder;

import bin_tree.leetcode.TreeNode;


public class ConvertTree2linkedList {
    // 传入一个BST的根节点,就可以将其转为双向链表,且返回链表头
    public TreeNode Convert(TreeNode pRootOfTree) {
        if(pRootOfTree == null ||(pRootOfTree.left == null &&
                pRootOfTree.right == null)) {
            return pRootOfTree;
        }
        TreeNode left = Convert(pRootOfTree.left);
        TreeNode leftTail = left;
        while (leftTail != null && leftTail.right != null) {
            leftTail = leftTail.right;
        }
        if (leftTail != null) {
            leftTail.right = pRootOfTree;
            pRootOfTree.left = leftTail;
        }
        TreeNode right = Convert(pRootOfTree.right);
        if (right != null) {
            right.left = pRootOfTree;
            pRootOfTree.right = right;
        }
        return left == null ? pRootOfTree : left;
    }
}

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5691506.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存