目录
938. 二叉搜索树的范围和
题解: 递归(思路非常清晰,内含画解,强推!)和 中序排序 递归 将整棵树遍历一遍
方法一:部分遍历
思路
标签:深度优先遍历
题意:这个题字面含义很难理解,本意就是求出所有 X >= L 且 X <= R 的值的和
递归终止条件:
当前节点为 null 时返回 0
当前节点 X < L 时则返回右子树之和
当前节点 X > R 时则返回左子树之和
当前节点 X >= L 且 X <= R 时则返回:当前节点值 + 左子树之和 + 右子树之和
注意点:通过判断X的大小能够避免遍历全部树的节点,比如下方的动图中,3 这个值就没有必要遍历
// 并没有将整棵树遍历一遍
var rangeSumBST = function(root, L, R) {
if(!root)return 0;
if(root.val < L)return rangeSumBST(root.right, L, R);//根节点小于L,那就看它的右结点,因为右结点值比根节点大。左结点不用考虑了。
if(root.val > R)return rangeSumBST(root.left, L, R);
return root.val + rangeSumBST(root.right, L, R) + rangeSumBST(root.left, L, R);
};
// 用一个思路,这次没有新建sum,直接靠return
var rangeSumBST = function(root, L, R) {
// let sum = 0;
return range(root, L, R);
// return sum;
function range(root, L, R){
if(!root)return 0;
if(root.val < L)return range(root.right, L, R);
if(root.val > R)return range(root.left, L, R);
return root.val + range(root.right, L, R) + range(root.left, L, R);
}
};
// 同一个思路,但新建了另一个函数
var rangeSumBST = function(root, L, R) {
let sum = 0;
range(root, L, R);
return sum;
function range(root, L, R){
if(!root)return 0;
if(root.val < L)return range(root.right, L, R);
if(root.val > R)return range(root.left, L, R);
// 改的时候曾写过:sum = root.val + range(root.right, L, R) + range(root.left, L, R),这个是会出错的,sum = NAN
sum = sum + root.val;
range(root.right, L, R);
range(root.left, L, R);
}
};
我以为没有将整棵树遍历一遍运行速度就会比较快,但是第一个代码是336ms,我以为慢的原因是递归了题目给我的函数,于是新建了一个函数,结果才320ms。下面的遍历整棵树,用先序的话会快到260ms左右...神奇了
方法二:全部遍历
// 将整棵树遍历一遍
var rangeSumBST = function(root, L, R) {
let sum = 0;
const inOrderNode = (node) => {
if(!node)return 0;//这个条件要放在递归前面,因为如果node是空,那node.left是不确定的。
// inOrderNode(node.left);//放在这里是中序遍历
if(node.val >= L && node.val <= R){
sum += node.val;
}
inOrderNode(node.left);//貌似放在这里,当先序遍历时比较快
inOrderNode(node.right);
}
inOrderNode(root);
return sum;
}
897. 递增顺序查找树
方法一:224ms
/**
* Definition for a binary tree node.
* function TreeNode(val) {
* this.val = val;
* this.left = this.right = null;
* }
*/
/**
* @param {TreeNode} root
* @return {TreeNode}
*/
var increasingBST = function(root) {
let res = [];
inOrderNode(root);
for(var i = 0; i < res.length-1; i++){//注意要用var,如果按我的思路(即,最后那个节点特殊处理)的话用let会错
res[i].left = null;
res[i].right = res[i+1];
}
// 最后那个节点
res[i].left = res[i].right = null;
// 注意要从0开始,为什么?不知道...可能是因为要求返回的是一个根节点叭
return res[0];
// 注意存的是节点
function inOrderNode(root){
if(!root)return null;
inOrderNode(root.left);
res.push(root);
inOrderNode(root.right);
}
};
下面那个代码和上面是一样的,只是为了留给自己看自己当时是怎么走了弯路的...
/**
* Definition for a binary tree node.
* function TreeNode(val) {
* this.val = val;
* this.left = this.right = null;
* }
*/
/**
* @param {TreeNode} root
* @return {TreeNode}
*/
var increasingBST = function(root) {
let res = [];
inOrderNode(root);
for(var i = 0; i < res.length-1; i++){//注意要用var,如果按我的思路let会错
res[i].left = null;
res[i].right = res[i+1];
}
// 最后那个节点
res[i].left = res[i].right = null;
//都不需要诶。注意res也是树就好了。
// let apple = [];
// preOrderNode(res[0]);//这句!!赶紧记住!res这个树是这么用的
// console.log(apple);
// for(let j = 0; j < res.length; j++){
// apple.push(res[j].val, res[j].left);
// }
// console.log(apple);
// 注意要从0开始,为什么?不知道...可能是因为要求返回的是一个根节点叭
return res[0];
// 注意存的是节点
function inOrderNode(root){
if(!root)return null;
inOrderNode(root.left);
res.push(root);
inOrderNode(root.right);
}
// console.log(res);
// function preOrderNode(root){
// if(!root){
// apple.push(null);
// return null;
// }
// apple.push(root.val);
// preOrderNode(root.left);
// preOrderNode(root.right);
// }
};
方法二:332ms
根据官方题解方法一做的
// 越来越慢...332ms
var increasingBST = function(root) {
let res = [];
inOrderNode(root);
console.log(res);
let ans = new TreeNode();
let cur = ans;
for(let i of res){
cur.right = new TreeNode(i);
cur = cur.right;
}
return ans.right;
function inOrderNode(root){
if(!root)return null;
inOrderNode(root.left);
res.push(root.val);
inOrderNode(root.right);
}
}
方法三:348ms
根据官方题解方法二做的 348ms(这么慢吗
var increasingBST = function(root) {
// 和let res = new TreeNode();结果一样
// let res = {
// left : null,
// right : null
// };
let res = new TreeNode();
let cur = res;
inOrderNode(root);
return cur.right;
//不加right:[undefined,null,1,null,2,null,3,null,4,null,5,null,6,null,7,null,8,null,9]
//加了right:[1,null,2,null,3,null,4,null,5,null,6,null,7,null,8,null,9]
// 注意存的是节点
function inOrderNode(node){
if(!node)return null;
inOrderNode(node.left);
node.left = null;
res.right = node;
res = node;
inOrderNode(node.right);
}
};
方法四:(辅助栈)
var increasingBST = function(root) {
let s = [];
let res = new TreeNode();
let p = res;
while(root || s.length){//之前出错原因:将s.length简写成s。后者是c语言的想法,判断s是否为空。但是js中判断非空是看s栈的长度是否为0
if(root){
s.push(root);
root = root.left;
}else{
let cur = s.pop();
root = cur.right;
cur.left = null;
p.right = cur;
p = p.right;
}
}
return res.right;
}