669. 修剪二叉搜索树
题目链接:669. 修剪二叉搜索树
文档讲解:代码随想录/修剪二叉搜索树
视频讲解:视频讲解-修剪二叉搜索树
状态:已完成(1遍)
解题过程
看到题目的第一想法
感觉还是删除二叉树的变种。我想着每层递归内对当前节点值进行判断,如果在区间内,则左右子节点继续递归下去;如果比最小值还小,那么这个节点的整个左子树肯定没用了;同理如果比最大值还大,这个节点的整个右子树肯定没用了;
手搓代码如下:
/**
* 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
* @param {number} low
* @param {number} high
* @return {TreeNode}
*/
var trimBST = function(root, low, high) {
let deleteNode = function(node){
if(node == null)return null;
if(node.val>=low&&node.val<=high){//在这之间的话,左右还是正常的递归下去
node.left = deleteNode(node.left);
node.right = deleteNode(node.right);
return node;
}else if(node.val<low){//比最低值还小,说明这个节点的左节点也没用了
node = deleteNode(node.right);
return node;
}else if(node.val>high){//比最大值还大,说明这个节点的右节点也没用了
node = deleteNode(node.left);
return node;
}
}
return deleteNode(root);
};
提交没有问题。
看完代码随想录之后的想法
讲解代码的思路跟我差不多,区别可能就在他有明确的当前递归层的处理逻辑,而我是直接融入终止递归条件中了。
讲解代码如下:
/**
* 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
* @param {number} low
* @param {number} high
* @return {TreeNode}
*/
var trimBST = function (root,low,high) {
if(root === null) {
return null;
}
if(root.val < low) {
let right = trimBST(root.right, low, high);
return right;
}
if(root.val > high) {
let left = trimBST(root.left, low, high);
return left;
}
root.left = trimBST(root.left, low, high);
root.right = trimBST(root.right, low, high);
return root;
}
总结
相比于删除某个节点来说,节点若不符合区间的话处理起来方便很多。
108.将有序数组转换为二叉搜索树
题目链接:108.将有序数组转换为二叉搜索树
文档讲解:代码随想录/将有序数组转换为二叉搜索树
视频讲解:视频讲解-将有序数组转换为二叉搜索树
状态:已完成(1遍)
解题过程
看到题目的第一想法
很眼熟的题目,之前有道最大二叉树也是将一个数组中最大的数字提取出来作为当前节点,印象很深的是当时我自己递归传参传的是一个新数组,卡哥给的解法是传递两个索引。那么这道题既然要求要构建一个平衡二叉搜索树,那么我每次取的节点值都一定要在当前数组的中间。
手搓代码如下:
/**
* 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 {number[]} nums
* @return {TreeNode}
*/
var sortedArrayToBST = function (nums) {
const balance = function (left, right) {
if (left > right) return null;
else {
let mid = Math.round((left + right) / 2);
let node = new TreeNode(nums[mid]);
node.left = balance(left,mid-1);
node.right = balance(mid+1,right);
return node;
}
}
return balance(0,nums.length-1);
};
提交没有问题。
看完代码随想录之后的想法
讲解代码和我几乎一模一样,惊了。略有成就感。
总结
给数组构造二叉树,可以在传参时只传索引,不传数组来提高速度。
538.把二叉搜索树转换为累加树
题目链接:538.把二叉搜索树转换为累加树
文档讲解:代码随想录/把二叉搜索树转换为累加树
视频讲解:视频讲解-把二叉搜索树转换为累加树
状态:已完成(1遍)
解题过程
看到题目的第一想法
读题都没读懂。。。什么叫使每个节点 node
的新值等于原树中大于或等于 node.val
的值之和???
看完代码随想录之后的想法
讲解之后才知道累加树的具体含义,自己的节点值加上比自己节点值大的所有节点值就是自己的新节点值。
看了讲解手搓代码如下:
/**
* 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 {TreeNode}
*/
var convertBST = function (root) {
let pre = 0;
const addTree = function (node) {
if (node == null) return;
addTree(node.right);
node.val += pre;
pre = node.val;
addTree(node.left);
return node;
}
return addTree(root);
};
没想到提交214/215。。原来是空数组的情况下我输出的是undefined。看了眼文字讲解发现最后输出写的略有区别。
文字讲解代码如下:
/**
* 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 {TreeNode}
*/
var convertBST = function (root) {
let pre = 0;
const addTree = function (node) {
if (node == null) return;
addTree(node.right);
node.val += pre;
pre = node.val;
addTree(node.left);
return node;
}
addTree(root);
return root;
};
这样就没有问题了。
总结
这道题的后序并不是机械的左右中,而是为了迎合题目的要求,从右往左,用的右中左。