算法刷题:树结构三题(2)

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)=2
f(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&&current.val>big.val&&Small==null){
            Small=previous;
        }
        recursion(root.right);
    }
}

题目来源 力扣网。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值