530. 二叉搜索树的最小绝对差
链接
文章链接
题目链接
第一想法
由于昨天做过搜索二叉树的题,所以立马就想到了用中序遍历,所以尝试用添加辅助数组的方式进行求解,代码如下:
function getMinimumDifference(root: TreeNode | null): number {
let res:number[]=[]
const foo=(root: TreeNode | null)=>{
if(root==null) return
foo(root.left)
res.push(root.val)
foo(root.right)
}
foo(root)
let num:number=Number.MAX_SAFE_INTEGER
for(let i=1;i<res.length;i++){
num=Math.min(res[i]-res[i-1],num)
}
return num
};
看完文章后的想法
文章用递归法和迭代法两种方案解决了这个问题,这里详细讲述递归法的两种方法,辅助数组法和双指针法。辅助数组法和上面我写的类型,下面的代码是双指针法,核心思想是记录递归节点的前一个节点,详细图为:
代码如下:
function getMinimumDifference(root: TreeNode | null): number {
let pre:TreeNode|null=null
let num:number=Number.MAX_SAFE_INTEGER
const foo=(root: TreeNode | null)=>{
if(root==null) return
foo(root.left)
if(pre!=null){
num=Math.min(num,root.val-pre.val)
}
pre=root
foo(root.right)
}
foo(root)
return num
};
思考
由于昨天了解过搜索二叉树的性质,所以今天做这道题不是很难,目前能熟悉掌握递归法的辅助数组的方法,对于双指针法目前是第一次进行尝试,需要多加琢磨。
501. 二叉搜索树中的众数
链接
文章链接
题目链接
第一想法
因为是搜索二叉树,所以万能用辅助数组法可以解决,所以这道题尝试直接在递归中修改,核心思想是也是辅助数组,但是这个辅助数组是在递归中的,数组用于存储相同val,如果遇到不相同的val,则进行判断,看是否是众数,如果是则存储到res中,代码如下:
function findMode(root: TreeNode | null): number[] {
let res:number[]=[]
let nums:number[]=[]
let max=0 //记录达到多少个数才是众数
const dfs=(root: TreeNode | null)=>{
if(root==null) return
dfs(root.left)
if(nums.length>0&&root.val>nums[nums.length-1]){ //如果当前节点的数和存储的数不相同,则进行判断数组里面的数是不是众数
if(max<nums.length){ //新的众数
max=nums.length
res=[nums[0]]
nums=[]
}else if(max==nums.length){//和res里面都是众数
res.push(nums[0])
nums=[]
}else nums=[] //不是众数
}
nums.push(root.val)
dfs(root.right)
}
dfs(root)
if(max<nums.length) return [nums[0]]
if(max==nums.length) res.push(nums[0])
return res
};
看完文章后的想法
代码随想录中用了三种方法求解,总体分为两类:递归法和迭代法,递归法中有两种,应该是应对一般二叉树的解法,用map统计,最后转化为数组进行求解,这里给出针对二叉搜索树的解法,利用中序遍历和双指针的方法,可以得出结果,代码如下:
function findMode(root: TreeNode | null): number[] {
let res:number[]=[]
let count:number=0 //计算相同元素的个数
let pre:TreeNode|null=null
let max:number=0
const dfs=(root: TreeNode | null)=>{
if(root==null) return
dfs(root.left)
if(pre==null){ //前一个节点为null则重置count
count=1
}else if(root.val==pre.val) count++ //当前节点val与前一个节点val相同 count++
else count=1 //当前节点val与前一个节点val不相同 重置count
if(count==max) res.push(root.val) //用于判断是否是众数
if(count>max){
max=count
res=[root.val]
}
pre=root
dfs(root.right)
}
dfs(root)
return res
};
思考
这道题不算很难,如果是一般二叉树直接用map进行统计后再求解,如果是搜索二叉树,就可以用二叉搜索树的性质进行求解,但是要注意pre为null和pre.val!=root.val的时候要重置,同时也要注意如何求众数,这是第一次尝试直接在递归过程中求解,值得纪念。
236. 二叉树的最近公共祖先
链接
文章链接
题目链接
第一想法
题目要求找到节点深度尽量大的公共节点,想法是用后序遍历,找到的话就返回true,如果左右节点都是true,则返回的就是公共节点。尝试一下:
function lowestCommonAncestor(root: TreeNode | null, p: TreeNode | null, q: TreeNode | null): TreeNode | null {
const dfs=(root: TreeNode | null)=>{
if(root==null) return false //终止条件
let left:boolean|TreeNode=dfs(root.left) //获取左节点返回的值
let right:boolean|TreeNode=dfs(root.right) //右节点返回的值
if(root.val==q.val||root.val==p.val){//这个条件是判断 一个节点正好是他的祖先的情况
return (left||right)?root:true //如果左右节点其中一个返回的是true 则返回当前节点(当前节点就是公共节点)
}
if(left===true&&right===true){//这种是左右孩子都找到了符合q||p的节点,所以目前节点是最深公共节点
return root
}
if(typeof left!='boolean' || typeof right !="boolean"){ //如果返回的是节点的话 直接返回这个节点
return typeof left!='boolean' ?left :right
}
//一般情况 如果左右孩子找到了符合目标的节点 则返回true,否则返回false
return left||right
}
return dfs(root)
};
看完文章后的想法
文章的核心思想和我的一样,都是利用后序遍历(包含回溯)的方法进行求解,唯一不同的情况是文章值的返回值只有Treenode|null,不包括boolean,所以解题思路有以下几点:
- 当前节点等于q或p的情况下 直接返回当前节点 (这种情况下包括有一个节点是公共节点的情况,后序条件中会体现)
- 如果当前节点为null 返回null
- 获取当前左右孩子的返回值 如果都返回null则说明里面并不包含q和p,所以返回null
- 如果左右孩子都有返回值且不为null 则当前节点为公共节点
- 如果左孩子不为null 右孩子为null 则返回左孩子(对照1)
- 如果左孩子为null 右孩子不为null 则返回右孩子(对照1) 详细代码如下:
function lowestCommonAncestor(root: TreeNode | null, p: TreeNode | null, q: TreeNode | null): TreeNode | null {
const dfs=(root: TreeNode | null)=>{
if(root==null||root==q||root==p) return root
let left:TreeNode|null=dfs(root.left)
let right:TreeNode|null=dfs(root.right)
if(left!=null&&right!=null) return root
if(left==null) return right
if(right==null) return left
}
return dfs(root)
};
思考
这道题不太好像,自己虽然写出来了,但是思路没有那么清晰,自己懵懵懂懂的做出来了,文章配图加文字很好的讲解了这道题,如果大家看不懂我的思路,可以去代码随想录中查看更详细的文章讲解。
今日总结
今日耗时2.5小时 三道题各有各的不同,第一道题依靠昨天的想法很容易就写出来了,第二道题尝试不使用辅助的方法进行求解。第三道题懵懵懂懂的做出来了,但是文章帮助我很清晰耳朵理解了思路,总得来说,今天收获巨大。