力扣关于树的题目(二)(二叉搜索树)
二叉搜索树的问题
1. 二叉搜索树的属性
二叉搜索树的属性是一个节点的值大于左节点的值,小于右节点的值
1. 700. 二叉搜索树中的搜索
相当于二分搜索,根节点比较,如果小往右走,大往左走
/**
* @param {TreeNode} root
* @param {number} val
* @return {TreeNode}
*/
var searchBST = function(root, val) {
let res = null;
const getChildTree = (root) => {
if(!root) {
return;
}
res.push(root.val);
getChildTree(root.left);
getChildTree(root.right);
}
const backtrace = (root) => {
if(!root) {
return null;
}
if(root.val === val) {
res = root;
return;
}else if(root.val > val) {
backtrace(root.left)
}else if(root.val < val) {
backtrace(root.right)
}
}
backtrace(root)
return res;
};
2. 98. 验证二叉搜索树
中序遍历,比较大小
/**
* @param {TreeNode} root
* @return {boolean}
*/
let pre = null;
var isValidBST = function (root) {
let pre = null;
const inOrder = (root) => {
if (root === null)
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);
};
3. 530. 二叉搜索树的最小绝对差
要找最小绝对差,相邻的两个节点的一定的最小的,只需要比较相邻的节点的差值哪个更小
/**
* @param {TreeNode} root
* @return {number}
*/
var getMinimumDifference = function(root) {
let pre = -1;
let min = Infinity;
const backtrace = (root) => {
if (!root) {
return;
}
backtrace(root.left);
if (pre === -1) {
pre = root.val;
}else {
min = Math.min(min,root.val - pre);
pre = root.val;
}
backtrace(root.right);
}
backtrace(root)
return min;
};
-
又是中序遍历,数值一样的数,在中序遍历的时候一定是挨在一起的
/** * @param {TreeNode} root * @return {number[]} */ var findMode = function(root) { let maxCount = 1; let resNum = []; let currentCount = 1; let pre; const inorder = (root) => { if(!root) { return; } inorder(root.left); if(pre === undefined) { pre = root.val; }else if (pre === root.val) { currentCount++; }else { if(maxCount < currentCount){ maxCount = currentCount; resNum = []; resNum.push(pre); }else if(maxCount === currentCount) { resNum.push(pre) } pre = root.val; currentCount = 1; } inorder(root.right) } inorder(root); if (currentCount > maxCount) { resNum = []; resNum.push(pre); }else if(currentCount == maxCount) { resNum.push(pre); } return resNum; };
5. 538. 把二叉搜索树转换为累加树
这题是反中序遍历,右头左
,将右边的数累加再赋新的值给树
/**
* @param {TreeNode} root
* @return {TreeNode}
*/
var convertBST = function(root) {
let sum = 0;
const bianli = (root) => {
if (!root) {
return;
}
bianli(root.right)
sum += root.val;
root.val = sum;
bianli(root.left)
}
bianli(root)
return root;
};
6. 235. 二叉搜索树的最近公共祖先
实际上是路径问题,判断走左边还是走右边
/**
* @param {TreeNode} root
* @param {TreeNode} p
* @param {TreeNode} q
* @return {TreeNode}
*/
var lowestCommonAncestor = function(root, p, q) {
let res;
// make p is smaller
if(p.val > q.val) {
let tmp = p;
p = q;
q = tmp;
}
const order = (root) => {
if(!root) {
return null;
}
if((p.val < root.val && root.val < q.val) || root.val === q.val || root.val === p.val) {
res = root
return
}else if(root.val > q.val) {
order(root.left)
}else {
order(root.right)
}
}
order(root)
return res;
};
2. 二叉搜索树的修改和构造
1. 701. 二叉搜索树中的插入操作
经过每一个节点,判断下一个走左边还是右边,如果找到空的就插入
/**
* @param {TreeNode} root
* @param {number} val
* @return {TreeNode}
*/
var insertIntoBST = function(root, val) {
if (!root) {
return root = new TreeNode(val);
}
const inOrder = (root) => {
if (root.val < val) {
if (root.right) {
inOrder(root.right);
}else {
root.right = new TreeNode(val)
return;
}
}
if (root.val > val) {
if (root.left) {
inOrder(root.left);
}else {
root.left = new TreeNode(val)
return;
}
}
}
inOrder(root);
return root;
};
2. 450. 删除二叉搜索树中的节点
这里有两个问题,第一个是找到节点删除,删除之后构造新的二叉搜索树
构建新的二叉树的方法:找到节点,然后更改子树的结构:根节点变成root.right,找到root.right的最左子节点,然后在节点的左边镶上root.left
/**
* @param {TreeNode} root
* @param {number} key
* @return {TreeNode}
*/
var deleteNode = function(root, key) {
const inOrder = (root) => {
if (!root) {
return root;
}
// delete the node
if (root.val === key) {
if (!root.left) {
return root.right;
}
else if (!root.right) {
return root.left;
}else {
let cur = root.right;
while (cur.left) {
cur = cur.left;
}
cur.left = root.left;
root = root.right;
return root;
}
}
if (root.val > key) {
root.left = inOrder(root.left);
}
if (root.val < key) {
root.right = inOrder(root.right)
}
return root;
}
return inOrder(root)
};
3. 669. 修剪二叉搜索树
root根据val分成三种情况:
-
比low还小,更改root成右边的节点
-
比high还大,更改root成左边的节点
-
在范围内,返回root,但是重新定义他的左子树和右子树
/**
* @param {TreeNode} root
* @param {number} low
* @param {number} high
* @return {TreeNode}
*/
var trimBST = function(root, low, high) {
const bianli = (root,low,high) => {
if (!root) {
return null;
}
let node;
if (root.val < low) {
node = bianli(root.right,low,high)
}else if (root.val > high) {
node = bianli(root.left,low,high)
}else {
node = root;
node.left = bianli(root.left,low,high);
node.right = bianli(root.right,low,high)
}
return node;
}
return bianli(root,low,high)
};
4. 108. 将有序数组转换为二叉搜索树
跟二分查找有点相似,找到中间的节点,构造节点,再确定左子树,右子树
/**
* @param {number[]} nums
* @return {TreeNode}
*/
var sortedArrayToBST = function(nums) {
const makeTree = (start,end) => {
if (end < start) {
return null;
}
// let len = end - start + 1;
let mid = Math.floor(start + (end - start) / 2);
let root = new TreeNode(nums[mid]);
root.left = makeTree(start,mid-1);
root.right = makeTree(mid+1,end);
return root;
}
return makeTree(0,nums.length-1);
};
总结
- 二叉搜索树的属性问题一般是遍历和找路径两类,遍历首先考虑中序遍历,找路径就是判断下一步往左走还是往右走
- 构造(修改)二叉搜索树的一般思路:确定根节点,递归构造(修改)左子树和右子树
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· winform 绘制太阳,地球,月球 运作规律
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 上周热点回顾(3.3-3.9)