最近发现了一个挺厉害的人工智能学习网站,内容通俗易懂,风趣幽默,感兴趣的可以点击此链接进行查看:床长人工智能教程
废话不多说,请看正文!
1、完全二叉树的节点个数
给你一棵 完全二叉树 的根节点 root ,求出该树的节点个数。
完全二叉树 的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层,则该层包含 1~ 2h 个节点。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public int countNodes(TreeNode root) {
if(root == null){
return 0;
}
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
int sum = 0;
while(!queue.isEmpty()){
int len = queue.size();
while(len > 0){
TreeNode node = queue.poll();
sum++;
if(node.left != null){
queue.offer(node.left);
}
if(node.right != null){
queue.offer(node.right);
}
len--;
}
}
return sum;
}
}
2、验证二叉搜索树
给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。
有效 二叉搜索树定义如下:
节点的左子树只包含 小于 当前节点的数。
节点的右子树只包含 大于 当前节点的数。
所有左子树和右子树自身必须也是二叉搜索树。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
private Integer pre = null; // 保存上一个值
private boolean flag = true;
public boolean isValidBST(TreeNode root) {
inorder(root);
return flag;
}
/**
中序遍历
比较和上一个值的大小关系
*/
public void inorder(TreeNode root){
if(root == null){
return;
}
// 存在相反顺序
if(!flag){
return;
}
inorder(root.left);
// 相反的顺序
if(pre != null && pre >= root.val){
flag = false;
return;
}
pre = root.val;
inorder(root.right);
}
}
3、恢复二叉搜索树
给你二叉搜索树的根节点 root ,该树中的两个节点的值被错误地交换。请在不改变其结构的情况下,恢复这棵树。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
private TreeNode pre;//当前节点的前一个节点
private TreeNode first;//第一个错误的节点
private TreeNode second;//第二个错误的节点
public void recoverTree(TreeNode root) {
//递归的中序遍历
inorder(root);
//交换两个节点的值
int temp = first.val;
first.val = second.val;
second.val = temp;
}
//递归的中序遍历
private void inorder(TreeNode root) {
//递归的终止条件
if (root == null){
return;
}
//遍历左子节点
inorder(root.left);
//二叉搜索树的中序遍历是有序的,如果前一个节点比当
//前节点的值大,也就是说出现了逆序。如果first为空,
// 我们就把pre节点赋值给first。
if (first == null && pre != null && pre.val >= root.val) {
first = pre;
}
//如果first不为空,并且前一个节点比当前节点的值大,
//我们就把当前节点赋值给second。注意上面是把pre
//节点保存下来,而这里是把当前节点给保存下来。因为
//我们是拿当前节点和前一个节点比较的,比如二叉树中
//序遍历的结果是[1,5,3,4,2,6],明显是5和2进行了
//交换,第一个错误的地方是3小于5,所以要把5(pre)
//保存下来,而第二个错误的地方是2小于4(pre),所
//以要把2(当前节点)保存下来
if (first != null && pre != null && pre.val >= root.val) {
second = root;
}
pre = root;//更新pre节点
//遍历右子节点
inorder(root.right);
}
}
4、不同的二叉搜索树
给你一个整数 n ,求恰由 n 个节点组成且节点值从 1 到 n 互不相同的二叉搜索树 有多少种?返回满足题意的二叉搜索树的种数。
class Solution {
public int numTrees(int n) {
int[] dp = new int[n + 1];
dp[0] = 1;
dp[1] = 1;
for(int i = 2; i <= n; i++){
for(int j = 1; j <= i; j++){
dp[i] = dp[i] + dp[j - 1]* dp[i - j];
}
}
return dp[n];
}
}
5、左叶子之和
计算给定二叉树的所有左叶子之和。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public int sumOfLeftLeaves(TreeNode root) {
if (root == null) {
return 0;
}
int left = sumOfLeftLeaves(root.left); // 左
int right = sumOfLeftLeaves(root.right); // 右
int midValue = 0;
if (root.left != null && root.left.left == null && root.left.right == null) {
midValue = root.left.val;
}
return midValue + left + right; // 中
}
}
6、找树左下角的值
给定一个二叉树的 根节点 root,请找出该二叉树的最底层最左边节点的值。
假设二叉树中至少有一个节点。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
// 递归法
class Solution {
private int Deep = -1;
private int value = 0;
public int findBottomLeftValue(TreeNode root) {
value = root.val;
findLeftValue(root,0);
return value;
}
private void findLeftValue (TreeNode root,int deep) {
if (root == null){
return;
}
if (root.left == null && root.right == null) {
if (deep > Deep) {
value = root.val;
Deep = deep;
}
}
if (root.left != null){
findLeftValue(root.left,deep + 1);
}
if (root.right != null){
findLeftValue(root.right,deep + 1);
}
}
}
7、从前序与中序遍历序列构造二叉树
给定一棵树的前序遍历 preorder 与中序遍历 inorder。请构造二叉树并返回其根节点。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public TreeNode buildTree(int[] preorder, int[] inorder) {
return helper(preorder, 0, preorder.length - 1, inorder, 0, inorder.length - 1);
}
public TreeNode helper(int[] preorder, int preLeft, int preRight,
int[] inorder, int inLeft, int inRight) {
// 递归终止条件
if (inLeft > inRight || preLeft > preRight) return null;
// val 为前序遍历第一个的值,也即是根节点的值
// idx 为根据根节点的值来找中序遍历的下标
int idx = inLeft, val = preorder[preLeft];
TreeNode root = new TreeNode(val);
for (int i = inLeft; i <= inRight; i++) {
if (inorder[i] == val) {
idx = i;
break;
}
}
// 根据 idx 来递归找左右子树
root.left = helper(preorder, preLeft + 1, preLeft + (idx - inLeft),
inorder, inLeft, idx - 1);
root.right = helper(preorder, preLeft + (idx - inLeft) + 1, preRight,
inorder, idx + 1, inRight);
return root;
}
}
8、从中序与后序遍历序列构造二叉树
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public TreeNode buildTree(int[] inorder, int[] postorder) {
return build(postorder, 0, postorder.length - 1,inorder, 0, inorder.length - 1);
}
public TreeNode build(int[] postorder, int postLeft, int postRight,int[] inorder, int inLeft, int inRight) {
// base case
if (inLeft > inRight) {
return null;
}
// root 节点对应的值是后序遍历数组的最后一个元素
int rootVal = postorder[postRight];
// 找到 root 在中序遍历中的位置
int index = 0;
for (int i = 0; i <= inRight; i++) {
if (inorder[i] == rootVal) {
index = i;
break;
}
}
int leftSize = index - inLeft;
// 先构造出根节点
TreeNode root = new TreeNode(rootVal);
// 递归构造左右子树
root.left = build(postorder, postLeft, postLeft + leftSize - 1,inorder, inLeft, index - 1);
root.right = build(postorder, postLeft + leftSize, postRight - 1,inorder, index + 1, inRight);
// 返回根节点
return root;
}
}
9、二叉搜索树中的众数
给你一个含重复值的二叉搜索树(BST)的根节点 root ,找出并返回 BST 中的所有 众数(即,出现频率最高的元素)。
如果树中有不止一个众数,可以按 任意顺序 返回。
假定 BST 满足如下定义:
结点左子树中所含节点的值 小于等于 当前节点的值
结点右子树中所含节点的值 大于等于 当前节点的值
左子树和右子树都是二叉搜索树
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
ArrayList<Integer> resList+;
int maxCount;
int count;
TreeNode pre;
public int[] findMode(TreeNode root) {
resList = new ArrayList<>();
maxCount = 0;
count = 0;
pre = null;
findMode1(root);
int[] res = new int[resList.size()];
for (int i = 0; i < resList.size(); i++) {
res[i] = resList.get(i);
}
return res;
}
public void findMode1(TreeNode root) {
if (root == null) {
return;
}
findMode1(root.left);
// 计数
if (pre == null || root.val != pre.val) {
count = 1;
} else {
count++;
}
// 更新结果以及maxCount
if (count > maxCount) {
resList.clear();
resList.add(root.val);
maxCount = count;
} else if (count == maxCount) {
resList.add(root.val);
}
pre = root;
findMode1(root.right);
}
}
10、二叉搜索树的最小绝对差
给你一个二叉搜索树的根节点 root ,返回 树中任意两不同节点值之间的最小差值 。
差值是一个正数,其数值等于两值之差的绝对值。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
TreeNode pre;// 记录上一个遍历的结点
int result = Integer.MAX_VALUE;
public int getMinimumDifference(TreeNode root) {
if(root==null)return 0;
traversal(root);
return result;
}
public void traversal(TreeNode root){
if(root==null){
return;
}
//左
traversal(root.left);
//中
if(pre!=null){
result = Math.min(result,root.val-pre.val);
}
pre = root;
//右
traversal(root.right);
}
}