一、判断是不是完全二叉树
给定一个二叉树,确定他是否是一个完全二叉树。
完全二叉树的定义:若二叉树的深度为 h,除第 h 层外,其它各层的结点数都达到最大个数,第 h 层所有的叶子结点都连续集中在最左边,这就是完全二叉树。(第 h 层可能包含 [1~2h] 个节点)
数据范围:节点数满足 1≤n≤100

import java.util.*;
/*
* public class TreeNode {
* int val = 0;
* TreeNode left = null;
* TreeNode right = null;
* public TreeNode(int val) {
* this.val = val;
* }
* }
*/
public class Solution {
public boolean isCompleteTree (TreeNode root) {
// LinkedList支持存null而ArrayDeque不支持
Deque<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()) {
TreeNode poll = queue.poll();
if (poll == null) {
break;
}
queue.offer(poll.left);
queue.offer(poll.right);
}
while (!queue.isEmpty()) {
if (queue.poll() != null) {
return false;
}
}
return true;
}
}
运行结果

二、判断是不是平衡二叉树
输入一棵节点数为 n 二叉树,判断该二叉树是否是平衡二叉树。
在这里,我们只需要考虑其平衡性,不需要考虑其是不是排序二叉树
平衡二叉树(Balanced Binary Tree),具有以下性质:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。

import java.util.*;
/*
* public class TreeNode {
* int val = 0;
* TreeNode left = null;
* TreeNode right = null;
* public TreeNode(int val) {
* this.val = val;
* }
* }
*/
public class Solution {
private boolean res = true;
public boolean IsBalanced_Solution (TreeNode pRoot) {
res = true;
dfs(pRoot);
return res;
}
private int dfs(TreeNode root) {
if (root == null || !res) return 0;
int lH = dfs(root.left), rH = dfs(root.right);
if (Math.abs(lH - rH) > 1) {
res = false;
return 0;
}
return Math.max(lH, rH) + 1;
}
}
运行结果

三、二叉搜索树的最近公共祖先
给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。
1.对于该题的最近的公共祖先定义:对于有根树T的两个节点p、q,最近公共祖先LCA(T,p,q)表示一个节点x,满足x是p和q的祖先且x的深度尽可能大。在这里,一个节点也可以是它自己的祖先.
2.二叉搜索树是若它的左子树不空,则左子树上所有节点的值均小于它的根节点的值; 若它的右子树不空,则右子树上所有节点的值均大于它的根节点的值
3.所有节点的值都是唯一的。
4.p、q 为不同节点且均存在于给定的二叉搜索树中。
数据范围:
3<=节点总数<=10000
0<=节点值<=10000

import java.util.*;
/*
* public class TreeNode {
* int val = 0;
* TreeNode left = null;
* TreeNode right = null;
* public TreeNode(int val) {
* this.val = val;
* }
* }
*/
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
* @param root TreeNode类
* @param p int整型
* @param q int整型
* @return int整型
*/
public int lowestCommonAncestor(TreeNode root, int p, int q) {
// write code here
while (root.val != p && root.val != q) {
if (p < root.val && q < root.val) {
root = root.left;
} else if (p > root.val && q > root.val) {
root = root.right;
} else {
// 如果两个节点在这里产生了分歧, 那么这里就是最近公共祖先
return root.val;
}
}
// 其中一个节点值等于root.val, 那么root.val就是最近公共祖先
return root.val;
}
}
运行结果

四、在二叉树中找到两个节点的最近公共祖先
给定一棵二叉树(保证非空)以及这棵树上的两个节点对应的val值 o1 和 o2,请找到 o1 和 o2 的最近公共祖先节点。
数据范围:树上节点数满足 1≤n≤105 , 节点值val满足区间 [0,n)
要求:时间复杂度 O(n)

import java.util.*;
/*
* public class TreeNode {
* int val = 0;
* TreeNode left = null;
* TreeNode right = null;
* public TreeNode(int val) {
* this.val = val;
* }
* }
*/
/**
* NC102 在二叉树中找到两个节点的最近公共祖先
* @author d3y1
*/
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param root TreeNode类
* @param o1 int整型
* @param o2 int整型
* @return int整型
*/
public int lowestCommonAncestor (TreeNode root, int o1, int o2) {
// return solution1(root, o1, o2);
// return solution11(root, o1, o2);
// return solution2(root, o1, o2);
return solution22(root, o1, o2);
}
/**
* 层序遍历
* @param root
* @param o1
* @param o2
* @return
*/
private int solution1(TreeNode root, int o1, int o2) {
Queue<QueueNode> queue = new LinkedList<>();
queue.offer(new QueueNode(root, null));
ArrayList<Integer> list1 = new ArrayList<>();
ArrayList<Integer> list2 = new ArrayList<>();
QueueNode qNode, currNode;
TreeNode tNode;
while (!queue.isEmpty()) {
qNode = queue.poll();
tNode = qNode.treeNode;
if (tNode.val == o1) {
list1.add(o1);
currNode = qNode;
while (currNode.parent != null) {
currNode = currNode.parent;
list1.add(currNode.treeNode.val);
}
}
if (tNode.val == o2) {
list2.add(o2);
currNode = qNode;
while (currNode.parent != null) {
currNode = currNode.parent;
list2.add(currNode.treeNode.val);
}
}
if (tNode.left != null) {
queue.offer(new QueueNode(tNode.left, qNode));
}
if (tNode.right != null) {
queue.offer(new QueueNode(tNode.right, qNode));
}
}
if (list1.contains(o2)) {
return o2;
}
if (list2.contains(o1)) {
return o1;
}
for (int val : list1) {
if (list2.contains(val)) {
return val;
}
}
return -1;
}
private class QueueNode {
TreeNode treeNode = null;
QueueNode parent = null;
public QueueNode(TreeNode treeNode, QueueNode parent) {
this.treeNode = treeNode;
this.parent = parent;
}
}
//-----------------------------------------//
/**
* 层序遍历: 简化
* @param root
* @param o1
* @param o2
* @return
*/
private int solution11(TreeNode root, int o1, int o2) {
HashMap<Integer, Integer> parentMap = new HashMap<>();
Queue<TreeNode> queue = new LinkedList<>();
parentMap.put(root.val, -1);
queue.offer(root);
TreeNode tNode;
// o1 o2 都找到 -> 结束循环
while (!parentMap.containsKey(o1) || !parentMap.containsKey(o2)) {
if (!queue.isEmpty()) {
tNode = queue.poll();
if (tNode.left != null) {
queue.offer(tNode.left);
parentMap.put(tNode.left.val, tNode.val);
}
if (tNode.right != null) {
queue.offer(tNode.right);
parentMap.put(tNode.right.val, tNode.val);
}
}
}
HashSet<Integer> ancestorSet = new HashSet<>();
int val1 = o1;
while (parentMap.containsKey(val1)) {
ancestorSet.add(val1);
val1 = parentMap.get(val1);
}
int val2 = o2;
while (!ancestorSet.contains(val2)) {
val2 = parentMap.get(val2);
}
return val2;
}
//-------------------------------------------//
/**
* 后序遍历
* @param root
* @param o1
* @param o2
* @return
*/
private int solution2(TreeNode root, int o1, int o2) {
return postOrder(root, o1, o2).val;
}
private TreeNode postOrder(TreeNode root, int o1, int o2) {
if (root == null || root.val == o1 || root.val == o2) {
return root;
}
TreeNode left = postOrder(root.left, o1, o2);
TreeNode right = postOrder(root.right, o1, o2);
// 左子树 未找到
if (left == null) {
return right;
}
// 右子树 未找到
if (right == null) {
return left;
}
// 一在左 一在右
return root;
}
//-----------------------------------------------------//
/**
* 后序遍历
* @param root
* @param o1
* @param o2
* @return
*/
private int solution22(TreeNode root, int o1, int o2) {
return postorder(root, o1, o2);
}
private int postorder(TreeNode root, int o1, int o2) {
if (root == null) {
return -1;
}
if (root.val == o1 || root.val == o2) {
return root.val;
}
int left = postorder(root.left, o1, o2);
int right = postorder(root.right, o1, o2);
// 左子树 未找到
if (left == -1) {
return right;
}
// 右子树 未找到
if (right == -1) {
return left;
}
// 一在左 一在右
return root.val;
}
}
运行结果

五、序列化二叉树
请实现两个函数,分别用来序列化和反序列化二叉树,不对序列化之后的字符串进行约束,但要求能够根据序列化之后的字符串重新构造出一棵与原二叉树相同的树。
二叉树的序列化(Serialize)是指:把一棵二叉树按照某种遍历方式的结果以某种格式保存为字符串,从而使得内存中建立起来的二叉树可以持久保存。序列化可以基于先序、中序、后序、层序的二叉树等遍历方式来进行修改,序列化的结果是一个字符串,序列化时通过 某种符号表示空节点(#)
二叉树的反序列化(Deserialize)是指:根据某种遍历顺序得到的序列化字符串结果str,重构二叉树。

import java.util.*;
/*
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}
*/
public class Solution {
String Serialize(TreeNode root) {
StringBuilder res = new StringBuilder();
Deque<TreeNode> deque = new LinkedList<>();
deque.offer(root);
while (!deque.isEmpty()) {
TreeNode poll = deque.poll();
if (poll == null) {
res.append("#,");
} else {
res.append(poll.val).append(',');
deque.offer(poll.left);
deque.offer(poll.right);
}
}
return res.deleteCharAt(res.length() - 1).toString();
}
TreeNode Deserialize(String str) {
if (str == null || str.isEmpty() || "#".equals(str)) {
return null;
}
String[] strs = str.split(",");
TreeNode res = new TreeNode(Integer.valueOf(strs[0]));
Deque<TreeNode> deque = new ArrayDeque<>();
deque.offer(res);
for (int i = 2; i < strs.length; i += 2) {
TreeNode poll = deque.poll();
if (!"#".equals(strs[i - 1])) {
poll.left = new TreeNode(Integer.valueOf(strs[i - 1]));
deque.offer(poll.left);
}
if (!"#".equals(strs[i])) {
poll.right = new TreeNode(Integer.valueOf(strs[i]));
deque.offer(poll.right);
}
}
return res;
}
}
运行结果

六、重建二叉树
给定节点数为 n 的二叉树的前序遍历和中序遍历结果,请重建出该二叉树并返回它的头结点。
例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建出如下图所示。

import java.util.*;
/*
* public class TreeNode {
* int val = 0;
* TreeNode left = null;
* TreeNode right = null;
* public TreeNode(int val) {
* this.val = val;
* }
* }
*/
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param preOrder int整型一维数组
* @param vinOrder int整型一维数组
* @return TreeNode类
*/
public TreeNode reConstructBinaryTree (int[] preOrder, int[] vinOrder) {
return reConstructBinaryTree1(preOrder, 0, preOrder.length - 1, vinOrder, 0,
vinOrder.length - 1);
}
public TreeNode reConstructBinaryTree1 (int[] preOrder, int s1, int e1,
int[] vinOrder, int s2, int e2) {
System.out.println(String.format("%d %d | %d %d", s1, e1, s2, e2));
if (s1 > e1) return null;
TreeNode node = new TreeNode(preOrder[s1]);
int t = -999;
for (int i = 0; i <= e2 - s2; i++) {
if (vinOrder[s2 + i] == preOrder[s1]) {
t = i;
break;
}
}
node.left = reConstructBinaryTree1(preOrder, s1 + 1, s1 + t, vinOrder, s2,
s2 + t - 1);
node.right = reConstructBinaryTree1(preOrder, s1 + t + 1, e1, vinOrder,
s2 + t + 1, e2);
return node;
}
}
运行结果

1301



被折叠的 条评论
为什么被折叠?



