1.不同的二叉搜索树
给你一个整数 n ,求恰由 n 个节点组成且节点值从 1 到 n 互不相同的 二叉搜索树 有多少种?返回满足题意的二叉搜索树的种数。
解析
根据入参n,获取函数f(n)为最后的结果值,树结构有一个根节点,根节点有左右两个子节点,所以
根节点更换是一种,左右子节点为null或者一个节点时为一种.所以f(1)=1,f(2)=2,f(3)有两种情况,左右子节点各一个,和左右子节点一边为null,一边有两个,为了符合二叉搜索树的条件,所以f(3)=2*f(2)f(1)+f(1)=5,f(4)=2f(3)f(1)+2f(2)*f(1).
n又分两种情况,一种是n是偶数,一种是n是奇数,n是偶数时n能分成左右对称的两大类情况,n是奇数中间有一种单独情况。所以n是偶数时f(n)=2*f(n-1)f(1)+2f(n-2)f(1)+…2f(n/2)f(n-n/2-1),n是奇数时
f(n)=2f(n-1)f(1)+2f(n-2)*f(1)+…f(n/2)*f(n/2)
代码
public int numTrees(int n) {
if (n==1){
return 1;
}
if (n==2){
return 2;
}
int count=0;
//n是偶数
if (n%2==0){
for (int i =n-1; i >= n/2; i--) {
int i1 = n - i - 1;
count+= 2*numTrees(i1>1?i1:1)* numTrees(i);
}
//n是奇数
}else {
int i =n-1;
for (; i > n/2; i--) {
int i1 = n - i - 1;
count+=2*numTrees(i1>1?i1:1)* numTrees(i);
}
count+= numTrees(i)*numTrees(i);
}
return count;
}
2.N 叉树的层序遍历
给定一个 N 叉树,返回其节点值的层序遍历。(即从左到右,逐层遍历)。
树的序列化输入是用层序遍历,每组子节点都由 null 值分隔。
解析
写N 叉树的层序遍历前,先要会树的层序遍历,就是使用队列先进后出的特点,先将根节点放入队列,弹出的时候,将子节点放入队列,上一层的节点没出完,下一层的节点都排在后面。N 叉树的层序遍历和普通树的层序遍历没区别,就是每到新的一层要生成一个新的集合,做区分。
代码
public List<List<Integer>> levelOrder(Node root) {
List<List<Integer>> arrayLists = new ArrayList<>();
arrayLists.add(new ArrayList<>());
//队列
Queue<Node> nodes = new LinkedList<Node>();
//map记录每层最后一个节点
Map<Integer, Node> map = new HashMap<>();
//根节点放入队列
nodes.add(root);
int num=0;
while (nodes.peek()!=null){
//节点弹出队列
Node poll = nodes.poll();
arrayLists.get(num).add(poll.val);
//子节点加出队列
for (int i = 0; i < poll.children.size(); i++) {
nodes.add(poll.children.get(i));
if (i==poll.children.size()-1){
//本层未结束,不断向map中加,主键是层数
map.put(num,poll.children.get(i));
}
}
//新一层 创建新集合
if (poll==root||poll==map.get(num-1)){
arrayLists.add(new ArrayList<>());
num++;
}
}
arrayLists.remove(num);
return arrayLists;
}
3.恢复二叉搜索树
给你二叉搜索树的根节点 root ,该树中的两个节点被错误地交换。请在不改变其结构的情况下,恢复这棵树。
解析
二叉搜索树在中序遍历时,可以得到一个递增排序的序列,然后在这个序列里找到不对的两个节点,交换位置就好了。
代码
class Solution {
//不对的两个节点
TreeNode big=null;
TreeNode Small=null;
//记录当前节点和当前节点的上一节点
TreeNode previous=null;
TreeNode current=null;
public void recoverTree(TreeNode root) {
recursion(root);
if (Small==null){
Small=current;
}
//交换位置
int val = big.val;
big.val = Small.val;
Small.val = val;
}
//中序遍历
private void recursion(TreeNode root) {
if (big!=null&&Small!=null){
return;
}
if (root==null){
return;
}
recursion(root.left);
previous=current;
current=root;
//当有一个节点小于前一节点时,第一个异常节点
if (previous!=null&&big==null&&previous.val>current.val){
big=previous;
}
//第一个异常节点小于之后的节点时,第二个异常节点就找到了
if (big!=null&¤t.val>big.val&&Small==null){
Small=previous;
}
recursion(root.right);
}
}
题目来源 力扣网。