二叉树:108. 将有序数组转换为二叉搜索树、538. 把二叉搜索树转换为累加树、669. 修剪二叉搜索树

提示:努力生活,开心、快乐的一天


108. 将有序数组转换为二叉搜索树

题目链接:108. 将有序数组转换为二叉搜索树

💡解题思路

  1. 取数组中间节点作为分割点,然后递归左区间和右区间
  2. 递归三部曲:
  • 确定递归函数返回值及其参数:传入数组,然后就是左下标left和右下标right,定义的是左闭右闭区间,在不断分割的过程中,也会坚持左闭右闭的区间,这又涉及到我们讲过的循环不变量
  • 确定递归终止条件:区间是左闭右闭,所以当区间 left > right的时候,就是空节点了
  • 确定单层递归的逻辑:首先取数组中间元素的位置,注意数值越界问题,划分区间,root的左孩子接住下一层左区间的构造节点,右孩子接住下一层右区间构造的节点,最后返回root节点
  1. 迭代法:通过三个队列来模拟,一个队列放遍历的节点,一个队列放左区间下标,一个队列放右区间下标。

🤔遇到的问题

  1. 注意分割的区间,是左闭右闭
  2. 迭代法,while(nodeQue)和while (nodeQue.length)的区分

💻代码实现

递归法

var sortedArrayToBST = function(nums) {
    const buildTree = (arr, left, right) => {
        if (left > right) return null
        let mid = Math.floor(left + (right - left) / 2)
        //取数组中间位置的值为树的根节点
        let root = new TreeNode(arr[mid])
        //root的左孩子接住下一层左区间的构造节点
        root.left = buildTree(arr, left, mid - 1)
        //右孩子接住下一层右区间构造的节点
        root.right = buildTree(arr, mid + 1, right)
        return root
    }
    //左闭右闭
    return buildTree(nums,0,nums.length-1)
};

迭代法

var sortedArrayToBST = function (nums) {
    if (nums.length === 0) return null
    let root = new TreeNode(0)//初始根节点
    let nodeQue = [root] //放遍历的节点,并初始化
    let leftQue = [0]   //放左区间的下标,初始化
    let rightQue = [nums.length - 1]  // 放右区间的下标
    while (nodeQue.length) {
        let curNode = nodeQue.pop()
        let left = leftQue.pop()
        let right = rightQue.pop()
        let mid = Math.floor(left + (right - left) / 2)
        //将下标为mid的元素给中间节点
        curNode.val = nums[mid]
        //处理左区间
        if (left <= mid - 1) {
            curNode.left = new TreeNode(0)
            nodeQue.push(curNode.left)
            leftQue.push(left)
            rightQue.push(mid - 1)
        }
        //处理右区间
        if (right >= mid + 1) {
            curNode.right = new TreeNode(0)
            nodeQue.push(curNode.right)
            leftQue.push(mid + 1)
            rightQue.push(right)
        }
    }
    return root
};

🎯题目总结

但凡是构造二叉树,逻辑基本是一样的,不断中间分割,然后递归处理左区间,右区间,也可以说是分治

538. 把二叉搜索树转换为累加树

题目链接:538. 把二叉搜索树转换为累加树

💡解题思路

  1. 从树中可以看出累加的顺序是右中左,所以我们需要反中序遍历这个二叉树,然后顺序累加就可以了,需要一个pre指针记录当前遍历节点cur的前一个节点在这里插入图片描述
  2. 递归遍历三部曲:
  • 递归函数参数以及返回值:因为要遍历整棵树,不需要递归函数的返回值做什么操作
  • 确定终止条件:遇空就终止
  • 确定单层递归的逻辑:右中左来遍历二叉树, 中节点的处理逻辑就是让cur的数值加上前一个节点的数值
  1. 迭代法:也是需要一个pre指针记录当前遍历节点cur的前一个节点,同时需要一个栈来存放节点

🤔遇到的问题

  1. pre的节点需要定义在递归外面
  2. 迭代法需要一直找到最右的节点

💻代码实现

递归法

var convertBST = function (root) {
    // 记录前一个节点的数值
    let pre = 0
    const addNode = (node) => {
        if (node) {
            //右
            addNode(node.right)
            //中
            node.val += pre
            pre = node.val
            //左
            addNode(node.left)
        }
    }
    addNode(root)
    return root
};

迭代法

var convertBST = function (root) {
    let pre = 0;
    let cur = root;
    let stack = [];//存放遍历的节点
    while (cur !== null || stack.length !== 0) {
        //找到最大的节点
        while (cur !== null) {
            stack.push(cur);
            //右
            cur = cur.right;
        }
        //中
        cur = stack.pop();
        cur.val += pre;
        pre = cur.val;
        //左
        cur = cur.left;
    }
    return root;
};

🎯题目总结

累加树,想清楚思路后,比其他二叉树的题回简单很多,终点需要注意:反中序遍历

669. 修剪二叉搜索树

题目链接:669. 修剪二叉搜索树

💡解题思路

  1. 特别注意:如下图**[1, 3]区间在二叉搜索树的中可不是单纯的节点3和左孩子节点0就决定的,还要考虑节点0的右子树**,图中我们发现节点0并不符合区间要求,那么将节点0的右孩子 节点2 直接赋给 节点3的左孩子就可以了(就是把节点0从二叉树中移除)
    在这里插入图片描述
  2. 递归三部曲:
  • 确定递归函数的参数以及返回值:参数:root,low,high;需要返回值:返回的是删除某节点后需要传给上一层的值,比如,叶子节点被删除,返回给上一层null,中间节点被删除,返回的是该节点的孩子节点给上一层
  • 确定终止条件:修剪的操作并不是在终止条件上进行的,所以就是遇到空节点返回就可以了
  • 确定单层递归的逻辑:
    1、如果root(当前节点)的元素小于low的数值,那么应该递归右子树,并返回右子树符合条件的头结点;如上图中,相当于把节点0的右孩子(节点2)返回给上一层
    2、如果root(当前节点)的元素大于high的,那么应该递归左子树,并返回左子树符合条件的头结点。
    3、将下一层处理完左子树的结果赋给root->left,处理完右子树的结果赋给root->right,如上图,相当于用节点3的左孩子 把下一层返回的 节点0的右孩子(节点2) 接住

🤔遇到的问题

  1. 逻辑有点绕,需要捋一下

💻代码实现

递归法

var trimBST = function(root, low, high) {
    if (root === null) return null
    //root(当前节点)的元素小于low的数值,那么应该递归右子树,并返回右子树符合条件的头结点。
    if (root.val < low) {
        return trimBST(root.right,low,high)// 寻找符合区间[low, high]的节点
    }
    //root(当前节点)的元素大于high的,那么应该递归左子树,并返回左子树符合条件的头结点。
    if (root.val > high) {
        return trimBST(root.left,low,high)// 寻找符合区间[low, high]的节点
    }
    root.left = trimBST(root.left, low, high)// root->left接入符合条件的左孩子
    root.right = trimBST(root.right, low, high)// root->right接入符合条件的右孩子
    return root
};

🎯题目总结

思路很难想到,看完视频和文章以后次啊能自己想明白,但细想一下有点绕,但不难

🎈今日心得

二叉树最后一天了,感觉该复习一下啦,这个周末的休息日,就好好复习一下二叉树吧

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值