530.二叉搜索树的最小绝对差
题目链接:530.二叉搜索树的最小绝对差
文档讲解:代码随想录/二叉搜索树的最小绝对差
视频讲解:视频讲解-二叉搜索树的最小绝对差
状态:已完成(2遍)
解题过程
看到题目的第一想法
二叉树转换成数组是一个有序数组,那么将其转换为数组之后,从数组中找最小差值就很方便,甚至都省去了绝对值的步骤。
手搓代码如下:
/**
* 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 ansArr = [];
const small = function(node){
if(node == null)return;
small(node.left);
ansArr.push(node.val);
small(node.right);
}
small(root);
let smallNum = Infinity;
for(let i = 0;i<ansArr.length-1;i++){
if((ansArr[i+1]-ansArr[i])<smallNum){
smallNum = ansArr[i+1]-ansArr[i];
}
}
return smallNum;
};
提交没有问题。
看完代码随想录之后的想法
讲解代码的思路大差不差,唯独定义输出值的时候略有不同,我定义的是极大值,他直接定义为数组里最大的值,想想也是,既然数组中所有值都大于等于0,那最小差值肯定不可能比最大的数要大。
讲解代码如下:
var getMinimumDifference = function (root) {
let arr = [];
const buildArr = (root) => {
if (root) {
buildArr(root.left);
arr.push(root.val);
buildArr(root.right);
}
}
buildArr(root);
let diff = arr[arr.length - 1];
for (let i = 1; i < arr.length; ++i) {
if (diff > arr[i] - arr[i - 1])
diff = arr[i] - arr[i - 1];
}
return diff;
};
总结
遇到在二叉搜索树上求什么最值啊,差值之类的,就把它想成在一个有序数组上求最值,求差值,这样就简单多了。
501.二叉搜索树中的众数
题目链接:501.二叉搜索树中的众数
文档讲解:代码随想录/二叉搜索树中的众数
视频讲解:视频讲解-二叉搜索树中的众数
状态:已完成(2遍)
解题过程
看到题目的第一想法
我的想法依旧是将二叉树转换为有序数组,再通过对数组中找出重复出现的数字来完成题目的要求。
手搓代码如下:
/**
* 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 nodeArr = [];
const makeArr = function (node) {
if (node == null) return;
makeArr(node.left);
nodeArr.push(node.val);
makeArr(node.right);
}
makeArr(root);
if (nodeArr.length == 1) return nodeArr;
let ans = [];
for(let i =1;i<nodeArr.length;i++){
if(nodeArr[i]==nodeArr[i-1]){
if(ans.length == 0)ans.push(nodeArr[i]);
else if(ans.length!=0&&ans[ans.length-1]==nodeArr[i]){
ans.push(nodeArr[i]);
}
}
}
return ans;
};
很奇怪提交的时候出现这种例子导致不通过。
不是说含有重复值的二叉树吗??
看完代码随想录之后的想法
看了视频讲解和文字讲解之后,发现还是错误理解题目的意思了。出现一次也算是当前数组中出现最多的。
这道题运用二叉树里的双指针pre和cur,能在只遍历一次的情况下就完成对众数的检测。
讲解代码如下:
/**
* 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) {
// 不使用额外空间,使用中序遍历,设置出现最大次数初始值为1
let count = 0,maxCount = 1;
let pre = root,res = [];
// 1.确定递归函数及函数参数
const travelTree = function(cur) {
// 2. 确定递归终止条件
if(cur === null) {
return ;
}
travelTree(cur.left);
// 3. 单层递归逻辑
if(pre.val === cur.val) {
count++;
}else {
count = 1;
}
pre = cur;
if(count === maxCount) {
res.push(cur.val);
}
if(count > maxCount) {
res = [];
maxCount = count;
res.push(cur.val);
}
travelTree(cur.right);
}
travelTree(root);
return 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 findMode = function(root) {
// 使用递归中序遍历
let map = new Map();
// 1. 确定递归函数以及函数参数
const traverTree = function(root) {
// 2. 确定递归终止条件
if(root === null) {
return ;
}
traverTree(root.left);
// 3. 单层递归逻辑
map.set(root.val,map.has(root.val)?map.get(root.val)+1:1);
traverTree(root.right);
}
traverTree(root);
//上面把数据都存储到map
//下面开始寻找map里面的
// 定义一个最大出现次数的初始值为root.val的出现次数
let maxCount = map.get(root.val);
// 定义一个存放结果的数组res
let res = [];
for(let [key,value] of map) {
// 如果当前值等于最大出现次数就直接在res增加该值
if(value === maxCount) {
res.push(key);
}
// 如果value的值大于原本的maxCount就清空res的所有值,因为找到了更大的
if(value>maxCount) {
res = [];
maxCount = value;
res.push(key);
}
}
return res;
};
236. 二叉树的最近公共祖先
题目链接:236. 二叉树的最近公共祖先
文档讲解:代码随想录/二叉树的最近公共祖先
视频讲解:视频讲解-二叉树的最近公共祖先
状态:已完成(2遍)
解题过程
看到题目的第一想法
我的想法是如果要找共同祖先,应该是要用后序遍历,将子节点的信息拿到返回给父节点,再做判断。
分为以下情况:
- 此节点等于要找的某个节点,且此节点有某个子节点含有另一个要找的子节点:输出赋值;
- 此节点等于要找的某个节点,且此节点没有某个子节点含有另一个要找的子节点:return true;
- 此节点不等于要找的某个节点,且此节点两个子节点都含有另一个要找的子节点:输出赋值;
- 此节点不等于要找的某个节点,return 左右子节点是否有要找的值的或;
手搓代码如下:
/**
* 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) {
let ans = null;
const nearest = function(node){
if(node == null)return false;
let leftBo = nearest(node.left);
let rightBo =nearest(node.right);
if(node== p||node== q){
if(leftBo||rightBo){//如果当前节点等于某个值且子节点中含有另一个值
ans = node;
}else{//如果当前节点等于某个值且子节点中不含有另一个值
return true;
}
}else{//当前节点不等于某个值
if(leftBo&&rightBo){
ans = node;
}else{
return leftBo||rightBo;
}
}
}
nearest(root);
return ans;
};
提交没有问题,卡尔哥说这题比较难,自己直接做出来成就感还是满满的。
看完代码随想录之后的想法
讲解的代码简便多了,判断的方式也有所区别。如果当前值是空值,就返回null,如果当前值是要找的节点,返回当前节点。
当前递归中的处理逻辑就看,如果左右的返回值都不是null,也就说明找到了,直接返回最近的祖先。
讲解代码如下:
/**
* 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) {
// 使用递归的方法
// 需要从下到上,所以使用后序遍历
// 1. 确定递归的函数
const travelTree = function(root,p,q) {
// 2. 确定递归终止条件
if(root === null || root === p || root === q) {
return root;
}
// 3. 确定递归单层逻辑
let left = travelTree(root.left,p,q);
let right = travelTree(root.right,p,q);
if(left !== null && right !== null) {
return root;
}
if(left === null) {
return right;
}
return left;
}
return travelTree(root,p,q);
};
总结
这种需要一层一层向上传递的,直接无脑后序。