力扣日记11:二叉树3

98. 验证二叉搜索树
  • 两种方法,一种是将树中序遍历转换为数组,比较是否递增
var isValidBST = function(root) {
    let arr = [];
    const inorder = (node) => {
        if (!node) return;
        node.left && inorder(node.left);
        arr.push(node.val);
        node.right && inorder(node.right);
    }
    inorder(root);
    for (let i = 1; i < arr.length; i++) {
    	// 注意这里的等号,会有特例[2,2,2]
        if (arr[i - 1] >= arr[i]) {
            return false;
        }
    }
    return true;
};
  • 第二种方法迭代,同样是比较升序,利用中序遍历将中间节点和前一个节点值进行比较
var isValidBST = function(root) {
    let pre = null;
    const inOrder = (root) => {
        if (!root) return true;
        let left = inOrder(root.left);
        if (pre !== null && pre.val >= root.val) return false;
        pre = root;
        let right = inOrder(root.right);
        return left && right;
    }
    return inOrder(root);
};
530. 二叉搜索树的最小绝对差
  • 和上题相似
var getMinimumDifference = function(root) {
    let arr = [], res = Number.MAX_VALUE;
    const inOrder = (node) => {
        if (!node) return;
        node.left && inOrder(node.left);
        arr.push(node.val);
        node.right && inOrder(node.right);
    }
    inOrder(root);
    for (let i = arr.length - 1; i > 0; i--) {
        let diff = arr[i] - arr[i - 1]
        res = res > diff ? diff : res;
    }
    return res;
};
var getMinimumDifference = function(root) {
    let pre = TreeNode(), res = Number.MAX_VALUE;
    const inOrder = (node) => {
        if (!node) return;
        node.left && inOrder(node.left);
        if (pre) {
            res = Math.min(res, node.val - pre.val);
        }
        pre = node;
        node.right && inOrder(node.right);
    }
    inOrder(root);
    return res;
};
501. 二叉搜索树中的众数
  • 最初是想将树转为数组然后判断众数的,代码非常的臃肿 在这里插入图片描述
  • 接下来介绍正确方法
  • 用额外空间map
var findMode = function(root) {
    let map = new Map();
    const inOrder = (node) => {
        if (!node) return;
        node.left && inOrder(node.left);
        map.set(node.val, map.has(node.val) ? map.get(node.val) + 1 : 1);
        node.right && inOrder(node.right);
    }
    inOrder(root);
    let res = [], cnt = map.get(root.val);
    map.forEach((value, key) => {
        if (cnt === value) {
            res.push(key);
        } else if (cnt < value) {
            cnt = value;
            res.length = 0;
            res.push(key);
        }
    })
    return res;
};
  • 顺便介绍一下js中数组的清空
let a = [1, 2, 3];
a.length = 0;	
// 赋予数组的长度length小于本身的长度,数组中后面的元素将被截断;赋予数组的长度length大于本身的长度,将扩展数组长度,多的元素为undefined。效率最高
a.splice(0);   
// splice清空,效率居中
a= [];  
// 直接置空,效率最低
  • 还有一种不需要map的,利用pre存储前一个节点来操作(暂时使用不是很熟练)
var findMode = function(root) {
    let res = [], pre = root, cnt = 0, maxCnt = 1;
    const inOrder = (node) => {
        if (!node) return;
        node.left && inOrder(node.left);
        if (pre.val === node.val) {
            cnt++;
        } else {
            cnt = 1;
        }
        pre = node;
        if (cnt === maxCnt) {
            res.push(node.val);
        } else if (cnt > maxCnt) {
            maxCnt = cnt;
            res.length = 0;
            res.push(node.val);
        }
        node.right && inOrder(node.right);
    }
    inOrder(root);
    return res;
};
236. 二叉树的最近公共祖先
  • 用后续遍历从底层向上传最近的祖先
  • 若一个子树中没有p或q节点,那么这棵子树的根节点会返回一个null;而如果有,从最近的公共祖先节点开始会将自己的节点通过后序遍历传递上来
var lowestCommonAncestor = function(root, p, q) {
     if (!root || root === p || root === q) return root;
     let left = lowestCommonAncestor(root.left, p ,q);
     let right = lowestCommonAncestor(root.right, p, q);
     if (left && right) return root;
     else if (left && !right) return left;
     else if (!left && right) return right;
     else return null;	//  (left == NULL && right == NULL)
};
235. 二叉搜索树的最近公共祖先
  • 和前一题写法稍有不同
  • 在递归函数有返回值时,我们需要确定要搜索一条边还是搜索整个树
    搜索一条边的写法:
if (递归函数(root->left)) return ;
if (递归函数(root->right)) return ;

搜索整个树的写法:

left = 递归函数(root->left);
right = 递归函数(root->right);
left与right的逻辑处理;
  • 那么前一题就是搜索整个树,这里就是搜索一条边
var lowestCommonAncestor = function(root, p, q) {
    if (!root) return root;
    if (root.val > p.val && root.val > q.val) {
        return lowestCommonAncestor(root.left, p, q);
    }
    if (root.val < p.val && root.val < q.val) {
        return lowestCommonAncestor(root.right, p, q);
    }
    return root;
};
  • 然鹅这题用迭代也十分简洁( ̄▽ ̄)/
var lowestCommonAncestor = function(root, p, q) {
    // 使用迭代的方法
    while(root) {
        if(root.val>p.val&&root.val>q.val) {
            root = root.left;
        }else if(root.val<p.val&&root.val<q.val) {
            root = root.right;
        }else {
            return root;
        }
        
    }
    return null;
};
701. 二叉搜索树中的插入操作
  • 根据搜索树的性质遍历到对应的空节点就行了
  • 创建一个节点时前面要加new(第一次忘记了然后找不出错╥﹏╥)
var insertIntoBST = function(root, val) {
    const travel = (node) => {
        if (!node) {
            return new TreeNode(val);
        }
        if (node.val < val) {
            node.right = travel(node.right);
        }
        if (node.val > val) {
            node.left = travel(node.left);
        }
        return node;
    }
    return travel(root);
};
450. 删除二叉搜索树中的节点
  • 有以下五种情况:

第一种情况:没找到删除的节点,遍历到空节点直接返回了找到删除的节点
第二种情况:左右孩子都为空(叶子节点),直接删除节点, 返回NULL为根节点
第三种情况:删除节点的左孩子为空,右孩子不为空,删除节点,右孩子补位,返回右孩子为根节点
第四种情况:删除节点的右孩子为空,左孩子不为空,删除节点,左孩子补位,返回左孩子为根节点
第五种情况:左右孩子节点都不为空,则将删除节点的左子树头结点(左孩子)放到删除节点的右子树的最左面节点的左孩子上,返回删除节点右孩子为新的根节点。
在这里插入图片描述

var deleteNode = function(root, key) {
    if (!root) return null;
    if (key > root.val) {
        root.right = deleteNode(root.right, key);
        return root;
    } else if (key < root.val) {
        root.left = deleteNode(root.left, key);
        return root;
    } else {
        // 场景1: 该节点是叶节点
        if (!root.left && !root.right) {
            return null
        }
        // 场景2: 有一个孩子节点不存在
        if (root.left && !root.right) {
            return root.left;
        } else if (root.right && !root.left) {
            return root.right;
        }
        // 场景3: 左右节点都存在
        const rightNode = root.right;
        // 获取最小值节点
        const minNode = getMinNode(rightNode);
        // 将待删除节点的值替换为最小值节点值
        root.val = minNode.val;
        // 删除最小值节点
        root.right = deleteNode(root.right, minNode.val);
        return root;
    }
};
function getMinNode(root) {
    while (root.left) {
        root = root.left;
    }
    return root;
}
108. 将有序数组转换为二叉搜索树
  • 整体思路就是二分
var sortedArrayToBST = function(nums) {
    const travel = (left, right) => {
        if (left > right) return null;
        let mid = left + Math.floor((right - left) / 2);
        let root = new TreeNode(nums[mid]);
        root.left = travel(left, mid - 1);
        root.right = travel(mid + 1, right);
        return root;
    }
    return travel(0, nums.length - 1);
};
538. 把二叉搜索树转换为累加树
  • 据题意确定遍历方式:右中左,然后将节点val累加即可
var convertBST = function(root) {
    let pre = 0
    const travel = (cur) => {
        if (!cur) return;
        travel(cur.right);
        cur.val += pre;
        pre = cur.val;
        travel(cur.left);
    }
    travel(root);
    return root;
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值