654. 最大二叉树
链接
文章链接
题目链接
第一想法
看到这道题,首先想到的就是按照给的算法进行模拟,代码如下:
function constructMaximumBinaryTree(nums: number[]): TreeNode | null {
const foo=(nums:number[])=>{
if(nums.length===0) return null
if(nums.length===1) return new TreeNode(nums[0])
//中
let max:number=Math.max(...nums)
let index:number=nums.indexOf(max)
let left:number[]=nums.slice(0,index)
let right:number[]=nums.slice(index+1,nums.length)
let node=new TreeNode(max)
node.left=foo(left) //左
node.right=foo(right)//右
return node
}
return foo(nums)
};
看完文章后的想法
文章的想法和我的想法类似,我的解法类似于文章中的优化版本,这里就不放置代码了。唯一的不同点是面对空数组我是走到下一层递归停止,而文章中是在本层就停止。由于昨天刚刚做完前序+中序构造二叉树,所以这道题不算很难。
思考
到目前为止已经做过三道构造二叉树的题了,其核心思想就是利用递归且为前序遍历,但是要有节点的返回,做了这三道题也是对这种题型越来越熟悉了。
617. 合并二叉树
链接
文章链接
题目链接
第一想法
依据题意也是构造二叉树,看到合并规则后,我认为有四个条件
- 两个节点都为null则返回null
- root1为null,root2不为null,则继续递归root2
- root1不为null,root2为null,则继续递归root1
- 两个节点都不为null,则两个节点都得递归,左节点和左节点一起递归,右节点和右节点一起递归
function mergeTrees(root1: TreeNode | null, root2: TreeNode | null): TreeNode | null {
const foo=(root1: TreeNode | null, root2: TreeNode | null)=>{
if(!root1&&!root2) return null
if(!root1&&root2){
let node =new TreeNode(root2.val)
node.left=foo(null,root2.left)
node.right=foo(null,root2.right)
return node
}
if(root1&&!root2){
let node =new TreeNode(root1.val)
node.left=foo(root1.left,null)
node.right=foo(root1.right,null)
return node
}
let node=new TreeNode(root1!.val+root2!.val)
node.left=foo(root1!.left,root2!.left)
node.right=foo(root1!.right,root2!.right)
return node
}
return foo(root1,root2)
};
看完文章后的想法
代码随想录中用了迭代法和递归法,这里主要说递归法,文章的递归法写的比我的好,因为题目要求是返回合并后的二叉树,所以可以不用构建新的二叉树,直接原地修改现有二叉树就可以了,代码如下:
function mergeTrees(root1: TreeNode | null, root2: TreeNode | null): TreeNode | null {
const foo=(root1: TreeNode | null, root2: TreeNode | null)=>{
if(!root1) return root2 //蕴含着root1和root2都为null的情况
if(!root2) return root1
root1.val+=root2.val
root1.left=foo(root1.left,root2.left)
root1.right=foo(root1.right,root2.right)
return root1
}
return foo(root1,root2)
};
思考
这道题可以用构造二叉树的方法,也可以在原来的二叉树上进行合并,两种方法都可以,主要练习构造二叉树的方法,这道题也不算太难,用于训练巩固。
700. 二叉搜索树中的搜索
链接
文章链接
题目链接
第一想法
文章是需要返回和目标值相同的节点,所以尝试递归法且不用辅助变量,直接后序遍历返回结果值,代码如下:
function searchBST(root: TreeNode | null, val: number): TreeNode | null {
const dfs:(root: TreeNode | null)=> TreeNode | null=(root: TreeNode | null)=>{
if(!root) return null
if(root.val==val) return root
return dfs(root.left) || dfs(root.right)
}
return dfs(root)
};
看完文章后的想法
文章用来两种方法,迭代法和递归法。同时还运用了搜索二叉树的性质来解决这个问题(节点的val小于右孩子的val大于左孩子的val),代码更加简洁: 递归法:
function searchBST(root: TreeNode | null, val: number): TreeNode | null {
const dfs:(root: TreeNode | null)=> TreeNode | null=(root: TreeNode | null)=>{
if(!root||root.val==val) return root
let node:TreeNode|null=null
if(root.val>val) node=dfs(root.left)
if(root.val<val) node=dfs(root.right)
return node
}
return dfs(root)
};
迭代法:
function searchBST(root: TreeNode | null, val: number): TreeNode | null {
while(root!=null){
if(root.val>val) root=root.left;
else if(root.val<val) root=root.right;
else return root
}
return null
};
思考
这道题主要是利用搜索二叉树的性质来解决,如果不知道搜索二叉树的性质,递归比较简单,但是如果知道搜索二叉树的性质,则迭代法非常简单。
98. 验证二叉搜索树
链接
文章链接
题目链接
第一想法
想不出来,有个简单的条件可以想出来,就是root.left.val<root.val<root.right.val,但是还有一个深层次的条件,节点A的右支的最大值要小于第一个在节点B(B的条件为左支中含有A),同理还有节点C的左支的最小值要大于第一个在节点D(D的条件为右支中含有A)。
看完文章后的想法
寄!!!!没想到,没想到。看完文章后茅塞顿开,用中序遍历,对于搜索二叉树来说,用中序遍历就可以得到一个从小到大严格升序的数组,我的第一想法太复杂了,不好实现。下面是用辅助数组的代码如下:
function isValidBST(root: TreeNode | null): boolean {
let nums:number[]=[]
const dfs=(root: TreeNode | null)=>{
if(root==null) return
dfs(root.left)//左
nums.push(root.val)//中
dfs(root.right)//右
}
dfs(root)
for(let i=1;i<nums.length;i++){
if(nums[i-1]>=nums[i]) return false
}
return true
};
思考
这道题如果想到中序遍历的话会很简单,如果想不到,就容易踩坑,踩完坑之后,发现逻辑非常复杂,不会写。这是第一次用中序遍历容易解决的问题,值得留念。
今日总结
今日耗时3小时,今天总共分为两部分,一部分为练习构建二叉树,另一部分是学习搜索二叉树以及搜索二叉树的性质,今天第一次遇到用中序遍历好解决的问题,值得留念。