代码随想录算法训练营第二十一天|530.二叉搜索树的最小绝对差 ● 501.二叉搜索树中的众数 ● 236. 二叉树的最近公共祖先 (JS写法)

530 二叉搜索树的最小绝对差

题目链接/文章讲解:https://programmercarl.com/0530.%E4%BA%8C%E5%8F%89%E6%90%9C%E7%B4%A2%E6%A0%91%E7%9A%84%E6%9C%80%E5%B0%8F%E7%BB%9D%E5%AF%B9%E5%B7%AE.html
视频讲解:https://www.bilibili.com/video/BV1DD4y11779
在这里插入图片描述

方法一:自己写的,先变成有序数组再处理

一开始以为直接把中序数组的第二个数字减第一个数字就可以了,但试了一下发现可能差值更小的在后面,后来画图发现都是两个两个这么计算,就想到了双指针滑动窗口

/**
 * 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
 * @return {number}
 */
var getMinimumDifference = function(root) {
    let arr = [];
    const inorder = (root) => {
        if(root === null) return null;
        inorder(root.left);
        arr.push(root.val);
        inorder(root.right);
    }
    inorder(root);
    let res = [];
    let i = 0,j = i+1;
    while(i<j && j<arr.length){
        res.push(arr[j]-arr[i]);
        i++;
        j++;
    }
    return Math.min(...res);

};

但是下面这种写法更好一点,只是新建了一个变量,我的方法是新建了一个数组。
在这里插入图片描述

方法二:在递归的过程中更新最小值

/**
 * 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
 * @return {number}
 */
var getMinimumDifference = function(root) {
    let res = Infinity;
    let pre = null;
    const inorder = (root) => {
        if(root === null) return null;
        inorder(root.left);
        if(pre) res = Math.min(res,root.val-pre.val);
        pre = root;
        inorder(root.right);
    }
    inorder(root);
    return res;
};

501 二叉搜索树中的众数

https://programmercarl.com/0501.%E4%BA%8C%E5%8F%89%E6%90%9C%E7%B4%A2%E6%A0%91%E4%B8%AD%E7%9A%84%E4%BC%97%E6%95%B0.html
视频讲解:https://www.bilibili.com/video/BV1fD4y117gp
在这里插入图片描述

方法一:自己写的(适用于求二叉树的众数)

自己想的思路,但是没有用上二叉搜索树的特性,而且感觉很麻烦,有很多小细节要注意

/**
 * 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
 * @return {number[]}
 */
var findMode = function(root) {
    if(root === null) return null;
    let arr = [];
    const inorder = (root) => {
        if(root === null) return null;
        inorder(root.left);
        arr.push(root.val);
        inorder(root.right);
    }
    inorder(root);
    const map = new Map();
    for(let i = 0;i<arr.length;i++){
        if(map.has(arr[i])){
            map.set(arr[i],map.get(arr[i])+1);
        }else{
            map.set(arr[i],1);
        }
    }
    let maxKey = [];
    let maxValue = -Infinity;
    for(const [key,value] of map){
        if(value > maxValue){
            maxValue = value;
            maxKey = [key];
        }else if(value === maxValue){ //如果相等这种情况也要列举出来
            maxKey.push(key);
        }
    }
    return maxKey;
};

方法二:笨猪爆破组

思路
访问每一个节点时,我们希望重复的节点值相邻被访问,便于:一边统计出现次数,一边看是否出现了最大出现次数。即,希望访问的节点值是有序的,对于 BST 来说,中序遍历能做到。本题的 BST 中序遍历,访问的节点值是非严格递增的。
处理当前的节点值
prev 变量,保存上一个出现的、不同的节点值。
modes 数组,保存出现次数最多的节点值们。
1、访问到一个重复的节点值,频次 freq +1
如果 freq 大于最大频次 maxFreq,更新 maxFreq,并且 modes 数组直接更新为[root.val],不使用原有数组。
如果 freq 等于 maxFreq,则将当前节点值加入 modes 数组。
如果 freq 小于 maxFreq,不造成影响,什么都不做。
2、访问到一个新的不同的节点值,频次 freq 归 1,并且更新 prev。之前的最高频次已经存到 maxFreq,现在要看新的节点值的频次,能否打破纪录。
如果 freq 大于最大纪录,更新 maxFreq,更新 modes 为 [root.val]。
如果 freq 等于 maxFreq,则将当前节点值加入 modes 数组。
如果 freq 小于 maxFreq,不造成影响,什么都不做。

/**
 * 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
 * @return {number[]}
 */
var findMode = function(root) {
    let modes = [];   //存储众数的数组
    let freq = 0;   //频次
    let maxFreq = 0;
    let prev = 0;  //存储上一个出现的,不同的节点值
    const handle = (rootVal) => {
        if(rootVal === prev){  //访问到重复的节点值
            freq++;
        }else{   //如果是不重复的节点值
            freq = 1;  //将频次归为1
            prev = rootVal;   //更新prev
        }
        //看频次是否能打破之前的maxFreg
        if(freq > maxFreq){  //频次大于之前保存的最大频次,即打破纪录
            maxFreq = freq;  //更新最大频次
            modes = [rootVal];   //更新modes数组
        }else if(freq === maxFreq){   //如果频次相等
            modes.push(rootVal);   //则push进去
        }
    }
    const inorder = (root) => {
        if(root === null) return null;
        inorder(root.left);
        handle(root.val);   //将处理节点这一步的逻辑抽出来
        inorder(root.right);
    }
    inorder(root);
    return modes;

};

236 二叉树的最近公共祖先

https://programmercarl.com/0236.%E4%BA%8C%E5%8F%89%E6%A0%91%E7%9A%84%E6%9C%80%E8%BF%91%E5%85%AC%E5%85%B1%E7%A5%96%E5%85%88.html
视频讲解:https://www.bilibili.com/video/BV1jd4y1B7E2
在这里插入图片描述

/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */
/**
 * @param {TreeNode} root
 * @param {TreeNode} p
 * @param {TreeNode} q
 * @return {TreeNode}
 */
var lowestCommonAncestor = function(root, p, q) {
    //如果当前节点本身为空,或者当前节点就是p或者q,则直接返回当前节点
    if(root === null || root === p || root === q){
        return root;
    }
    const left = lowestCommonAncestor(root.left,p,q);
    const right = lowestCommonAncestor(root.right,p,q);
    if(left && right){  //一个点在左子树,一个点在右子树,则直接返回当前节点
        return root;
    }
    if(left === null){  //如果左子树为空,即两个点都不在左子树中,则返回右节点
        return right;
    }
    return left;   //否则返回左节点
};

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值