LeetCode热题100JS(49/100)第九天|199|114|105|437|236
199. 二叉树的右视图
题目链接:199. 二叉树的右视图
难度:中等
刷题状态:2刷
新知识:
解题过程
思考
示例 1:
输入:root = [1,2,3,null,5,null,4]
输出:[1,3,4]
解释:
放下1刷过程在题解
题解分析
参考题解链接:【视频】如何灵活运用递归?(Python/Java/C++/Go/JS/Rust)
详细分析如下
/**
* 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 {number[]}
*/
var rightSideView = function(root) {
if(!root){
return []
}
let res=[]
function rightDepth(node,depth){
if(!node){
return
}
if(depth==res.length){
res.push(node.val)
}
rightDepth(node.right,depth+1)
rightDepth(node.left,depth+1)
}
rightDepth(root,0)
return res
};
手搓答案(无非废话版)
/**
* 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 {number[]}
*/
var rightSideView = function(root) {
let res=[]
function dfs(node,depth){
if(!node) return
if(res.length==depth) res.push(node.val)
dfs(node.right,depth+1)
dfs(node.left,depth+1)
}
dfs(root,0)
return res
};
总结
可以用res.length==depth来判断是否传入数据,注意right要先递归,这样才是传入右边的数据
114. 二叉树展开为链表
题目链接:114. 二叉树展开为链表
难度:中等
刷题状态:1刷
新知识:
解题过程
思考
示例 1:
输入:root = [1,2,5,3,4,null,6] 输出:[1,null,2,null,3,null,4,null,5,null,6]
题解分析
参考题解链接:详细通俗的思路分析,多解法
详细分析如下
/**
* 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 {void} Do not return anything, modify root in-place instead.
*/
var flatten = function(root) {
let pre=null
function dfs(node){
if(!node) return
首先递归地遍历当前节点的右子树。由于目标是构建右斜树,所以先处理右子树有助于保持相对顺序。
dfs(node.right)
dfs(node.left)
//将当前节点的右子节点设置为 pre,即前一个节点。这一步是构建右斜树的关键,它将当前节点的左子树之前的所有节点链接起来。
node.right=pre
//更新 pre 为当前节点。这样,在下一次迭代中,当前节点将成为下一个节点的“前一个节点”。
pre=node
node.left=null
}
dfs(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
* @return {void} Do not return anything, modify root in-place instead.
*/
var flatten = function(root) {
let pre=null
function dfs(node){
if(!node) return
dfs(node.right)
dfs(node.left)
node.right=pre
pre=node
node.left=null
}
dfs(root)
};
总结
可以用res.length==depth来判断是否传入数据,注意right要先递归,这样才是传入右边的数据
105. 从前序与中序遍历序列构造二叉树
题目链接:105. 从前序与中序遍历序列构造二叉树
难度:中等
刷题状态:2刷
新知识:
解题过程
思考
示例 1:
输入: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7] 输出: [3,9,20,null,null,15,7]
放下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[]} preorder
* @param {number[]} inorder
* @return {TreeNode}
*/
var buildTree = function(preorder, inorder) {
let dic={}
for(let i=0;i<inorder.length;i++){
dic[inorder[i]]=i
}
//开始递归
function dfs(pre,left,right){
if(left>right) return null
//创建根节点
let node=new TreeNode(preorder[pre])
//搜索preorder元素(根节点)在inorder中的索引
let i=dic[preorder[pre]]
//创建左子树
node.left=dfs(pre+1,left,i-1)
//创建右子树
node.right=dfs(pre+1+i-left,i+1,right)
return node
}
return dfs(0,0,inorder.length-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[]} preorder
* @param {number[]} inorder
* @return {TreeNode}
*/
var buildTree = function(preorder, inorder) {
let dic={}
for(let i=0;i<inorder.length;i++){
dic[inorder[i]]=i
}
function dfs(pre,left,right){
if(left>right) return null
let node=new TreeNode(preorder[pre])
let i=dic[preorder[pre]]
node.left=dfs(pre+1,left,i-1)
node.right=dfs(pre+1+i-left,i+1,right)
return node
}
return dfs(0,0,inorder.length-1)
};
总结
重点理解这两行
node.left=dfs(pre+1,left,i-1)
node.right=dfs(pre+1+i-left,i+1,right)
pre+1
:- 前序遍历中,
pre
是当前子树根节点的索引。 pre+1
是左子树根节点在前序遍历数组中的索引,因为前序遍历紧接着根节点访问左子树。
- 前序遍历中,
left
到i-1
:left
是当前子树在中序遍历中的起始索引。i
是根节点在中序遍历中的位置。i-1
是左子树在中序遍历中的结束索引。
因此,这一行代码通过递归调用 dfs
构建当前节点的左子树。
pre+1+i-left
:pre+1
是左子树根节点在前序遍历中的起始索引。i-left
是左子树中的节点数。- 因此,
pre+1+i-left
是右子树根节点在前序遍历中的起始索引。
i+1
到right
:i+1
是右子树在中序遍历中的起始索引。right
是当前子树在中序遍历中的结束索引。
这一行代码通过递归调用 dfs
构建当前节点的右子树。
437. 路径总和 III
题目链接:437. 路径总和 III
难度:中等
刷题状态:1刷
新知识:
解题过程
思考
示例 1:
输入:root = [10,5,-3,3,2,null,11,3,-2,null,1], targetSum = 8 输出:3 解释:和等于 8 的路径有 3 条,如图所示。
题解分析
参考题解链接:【视频】如何灵活运用递归?(Python/Java/C++/Go/JS/Rust)
详细分析如下
/**
* 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} targetSum
* @return {number}
*/
var pathSum = function(root, targetSum) {
let res=0
//用于记录遍历过程中遇到的前缀和及其出现的次数
let cnt=new Map()
//节点和为0的情况有1种
cnt.set(0,1)
//s记录当前路径上的节点之和
function dfs(node,s){
if(!node) return null
s+=node.val
// console.log(s-targetSum,cnt)
if(cnt.get(s-targetSum)){
//如果有,说明某个祖先节点到当前节点的路径和等于 targetSum
res+=cnt.get(s-targetSum)
}
if(!cnt.get(s)) cnt.set(s,0)
cnt.set(s,cnt.get(s)+1)
dfs(node.left,s)
dfs(node.right,s)
//复位
cnt.set(s,cnt.get(s)-1)
}
dfs(root,0)
return res
};
手搓答案(无非废话版)
/**
* 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} targetSum
* @return {number}
*/
var pathSum = function(root, targetSum) {
let cnt =new Map(),res=0
cnt.set(0,1)
function dfs(node,s){
if(!node) return null
s+=node.val
if(cnt.get(s-targetSum)){
res+=cnt.get(s-targetSum)
}
if(!cnt.get(s)) cnt.set(s,0)
cnt.set(s,cnt.get(s)+1)
dfs(node.left,s)
dfs(node.right,s)
cnt.set(s,cnt.get(s)-1)
}
dfs(root,0)
return res
};
总结
注意要先设置(0,1)的初值
236. 二叉树的最近公共祖先
题目链接:236. 二叉树的最近公共祖先
难度:中等
刷题状态:2刷
新知识:
解题过程
思考
示例 1:
输入:root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1 输出:3 解释:节点5
和节点1
的最近公共祖先是节点3 。
放下1刷过程在题解
题解分析
参考题解链接:【视频】如何灵活运用递归?(Python/Java/C++/Go/JS/Rust)
详细分析如下
/**
* Definition for a binary tree node.
* function TreeNode(val) {
* this.val = val;
* this.left = this.right = null;
* }
*/
/**
* @param {TreeNode} root
* @param {TreeNode} p
* @param {TreeNode} q
* @return {TreeNode}
*/
var lowestCommonAncestor = function(root, p, q) {
if(!root||root==p||root==q) return root
//递归地在当前节点的左子树中查找p和q的最低公共祖先,并将结果存储在left变量中。
let left=lowestCommonAncestor(root.left,p,q)
//递归地在当前节点的右子树中查找p和q的最低公共祖先,并将结果存储在right变量中。
let right=lowestCommonAncestor(root.right,p,q)
//这意味着p和q的最低公共祖先在右子树中,或者p和q中的一个就是right节点本身。
if(!left) return right
//这意味着p和q的最低公共祖先在左子树中,或者p和q中的一个就是left节点本身。
if(!right) return left
//如果left和right都不为null,说明p和q分别位于当前节点的左右两侧(或者其中一个就是当前节点)。在这种情况下,返回当前节点作为p和q的最低公共祖先。
return root
//return left && right ? root : left || right;
};
手搓答案(无非废话版)
/**
* Definition for a binary tree node.
* function TreeNode(val) {
* this.val = val;
* this.left = this.right = null;
* }
*/
/**
* @param {TreeNode} root
* @param {TreeNode} p
* @param {TreeNode} q
* @return {TreeNode}
*/
var lowestCommonAncestor = function(root, p, q) {
if(!root||root==p||root==q) return root
let left=lowestCommonAncestor(root.left,p,q)
let right=lowestCommonAncestor(root.right,p,q)
if(!left) return right
if(!right) return left
return root
};
总结
重点理解
if(!left) return right
if(!right) return left
这两个逻辑