首页 > 其他分享 >654.最大二叉树+998.最大二叉树II

654.最大二叉树+998.最大二叉树II

时间:2022-08-30 15:58:19浏览次数:57  
标签:right val nums II 654 二叉树 root 节点 left

654.最大二叉树

题目描述

  给定一个不重复的整数数组 nums 。 最大二叉树 可以用下面的算法从 nums 递归地构建:

  • 创建一个根节点,其值为 nums 中的 最大值 
  • 递归地在 最大值 左边 的 子数组前缀上 构建左子树。
  • 递归地在 最大值 右边 的 子数组后缀上 构建右子树。

  返回 nums 构建的 最大二叉树 。

 

解题思路

递归分治

  定义一个递归函数construct(nums, left, right),用来构建 nums[left] 到 nums[right] 这些节点形成的树:

  • 首先,找到区间 [left,right] 中最大值的位置maxIdx,创建值为 nums[maxIdx] 的节点作为根节点;
  • 然后,开始递归地构造根节点的左子树和右子树:
    • 左子树为 construct(nums, left, maxIdx-1)
    • 右子树为construct(nums, maxIdx+1, right)

代码实现:

 

/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {number[]} nums
 * @return {TreeNode}
 */
var constructMaximumBinaryTree = function(nums) {
    //递归函数
    function f(nums,left,right){
        if(left>right){
            return null;
        }
        let maxIdx = left;
        //找到区间中的最大值位置
        for(let i=left+1;i<=right;i++){
            if(nums[i]>nums[maxIdx]){
                maxIdx = i;
            }
        }
        let node = new TreeNode(nums[maxIdx]);
        node.left = f(nums,left,maxIdx-1); //构建左子树
        node.right = f(nums,maxIdx+1,right); //构建右子树
        return node;
    }
    return f(nums,0,nums.length-1);
};

 

 

单调栈

  我们从左往右遍历nums,定义当前遍历的元素为newNode,需要与newNode进行比较的节点为cur,可以保证前面操作的节点都位于newNode的左边。另外,用一个Map来存储各个节点的父节点(如果存在父节点)。遍历过程中的操作如下:

  • 若当前节点的值小于前一个节点,它应该添加到前一个节点的右子树;
  • 若当前节点的值大于前一个节点,它应该往上寻找父节点直到遇到一个大于当前节点值的父节点cur,而使用pre来保存前一个父节点。找到后,将pre添加到newNode的左子树,因为以pre为根的子树的所有节点的值都小于newNode且位于newNode的左边。
    • 如果cur不为undefined,表示存在比当前节点值大的节点,应该将当前节点添加到cur的右子树,同时保存两节点的父子关系到parent中;
    • 如果cur为undefined,表示当前节点值最大,应该作为整个数的根节点,因此将之前的根节点添加到newNode的左子树,并更新root。

 

代码如下:

 

/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {number[]} nums
 * @return {TreeNode}
 */
var constructMaximumBinaryTree = function(nums) {
    const parent = new Map();//用于保存节点间父子关系的Map
    
    //初始化,先将nums[0]作为根节点
    let root = new TreeNode(nums[0]);
    let cur = root;

    for(let i=1;i<nums.length;i++){
        let newNode = new TreeNode(nums[i]);
        if(nums[i]<nums[i-1]){
            cur.right = newNode;
            parent.set(newNode,cur);
        }else{
            let pre = null; //pre保存搜索过程中的前一个父节点

            //找到比nums[i]大的父节点,最后找不到时get()返回的是undefined
            while(cur!==undefined&&nums[i]>cur.val){
                pre = cur;
                cur = parent.get(cur);
            }

            newNode.left = pre;
            parent.set(pre,newNode);

            //当找到了比nums[i]大的父节点cur,把newNode添加到cur的右子树
            if(cur!==undefined){
                cur.right = newNode;
                parent.set(newNode,cur); //添加父子关系
            }else{ //若找不到符合的父节点,表示nums[i]值最大,它应该作为新的根节点
                root = newNode;
            }
        }
        cur = newNode;//更新cur为当前元素,方便后面遍历的元素进行重新比较
    }
    return root;
};

 

 

998.最大二叉树II

题目描述

  假设给定了一个数组a,通过《654.最大二叉树》中定义的方法构建好一棵最大二叉树,其根节点为root。现在,在数组a的末尾添加一个值val,形成了新的数组b,如何在已知root和val的基础上,构建新的最大二叉树?

 

解题思路

  定义一个递归函数f,返回值为重建的最大二叉树的根节点。

首先将val与root.val比较,

  • 若val>root.val,那么新节点node应该作为新的根节点,而已构建好的最大二叉树的根节点root应该添加到node的左子树(因为node在数组b中始终位于最右边);
  • 若val<root.val,由于node在数组b中始终位于最右边,那么node应该放置在root的右子树上,表示右子树需要重建,将重建后的新根子节点添加到当前root的右子树。如何得到重建后的新根子节点呢?只需要继续遍历右子树,也即更新root为root.right,重复上述操作。

 

代码如下:

/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @param {number} val
 * @return {TreeNode}
 */
var insertIntoMaxTree = function(root, val) {
    function f(root,val){
        if(val>root.val){
            let node = new TreeNode(val);
            node.left = root;
            return node;  //根节点改变了
        }else{
            if(root.right){
                let subRoot = f(root.right,val); //获取某右子树重建后的根节点
                root.right = subRoot;
            }else{
                let node = new TreeNode(val);
                root.right = node;
            }
            return root; //根节点没有改变,直接返回
        }
    }
    return f(root,val);
};

 

标签:right,val,nums,II,654,二叉树,root,节点,left
From: https://www.cnblogs.com/evil-shark/p/16639566.html

相关文章

  • 通信协议详解(一):IIC总线协议(传输时序+数据格式+设计实现) - 知乎
    一、IIC(Inter-IntegratedCircuit)介绍    IIC(Inter-IntegratedCircuit)即集成电路总线,它是一种具有两线传输的串行通信总线,使用多主从架构,由飞利浦公司在1980年代为了......
  • 2022-8-30 每日一题-二叉树递归-
    998.最大二叉树II难度中等90收藏分享切换为英文接收动态反馈最大树 定义:一棵树,并满足:其中每个节点的值都大于其子树中的任何其他值。给你最大树的根节点 root......
  • CF633H Fibonacci-ish II 莫队 线段树 矩阵
    CF633HFibonacci-ishII题意很简明同时给人以不可做感。直接暴力大概是\(n^2log\)的优化一下提前排好序从小到大枚举数字再枚举询问可以完成\(n^2\)经过精细的优化......
  • js 实现二叉树中序遍历
    varinorderTraversal=function(root){//迭代if(!root){return[];}letres=[];letstack=[];while(stack.length>......
  • Apache与IIS的优劣对比
    对于中小企业来说建立自己的网站,对外展示自己的页面是最平常不过的事情了。目前最流行的建立WWW服务工具就要属Apache与IIS了。那么他们之间都有什么区别呢?到底哪个工具才......
  • 「翻译」SAP制造集成和智能(SAP MII)
    SAP制造集成和智能(SAPMII)  集成和连接是成功的工业4.0计划的关键。SAPManufacturingIntegrationandIntelligence(SAPMII)是集成各种应用程序、设备和传感器并将......
  • 「翻译」SAP MII(SAP制造集成和智能)-灵活且可扩展
    SAPMII(SAP制造集成和智能)-灵活且可扩展    通过SAPMII,SAP提供了一个基于Web的、标准化和灵活的IT平台,用于垂直集成到生产中。这将面向流程的制造单元的生产......
  • VisualStudio启动项目提示“[xxxx] iisexpress.exe”已退出
    一、在通过VisualStudio直接启动项目时,iisexpress.exe直接退出1.程序“[6068]iisexpress.exe:程序跟踪”已退出,返回值为0(0x0)。2.程序“[6068]iisexpress.exe“已......
  • 【leetcode】81. 搜索旋转排序数组 II
    原题地址:https://leetcode.cn/problems/search-in-rotated-sorted-array-ii/用循环遍历数组肯定能轻松找到target但要尽可能减少操作步骤,一般跟顺序有关的都是用二分,关键......
  • js 实现二叉树前序遍历
    //前序遍历:根左右//中序遍历:左中右//后序遍历:左右根//迭代varpreorderTraversal=function(root){if(!root){returnnull;}//迭......