东哥带你刷二叉树(构造篇) :: labuladong的算法小抄 #1018
Replies: 74 comments 8 replies
-
囊中羞涩的小弟到此一游 |
Beta Was this translation helpful? Give feedback.
-
小建议~ class Solution {
public TreeNode constructMaximumBinaryTree(int[] nums) {
return getRoot(nums,0,nums.length-1);
}
TreeNode getRoot(int[] nums,int l,int r){
if(l>r) return null;
int m = l;
for(int i = l; i <= r; i++){
if(nums[i]>nums[m])
m = i;
}
TreeNode root = new TreeNode(nums[m]);
root.left = getRoot(nums,l,m-1);
root.right = getRoot(nums,m+1,r);
return root;
}
} |
Beta Was this translation helpful? Give feedback.
-
@Feyl 你这样循环体每次最大值都需要访问数组,从代码性能上来说还是用一个额外的变量来保存比较好(个人看法,大佬轻喷)(doge |
Beta Was this translation helpful? Give feedback.
-
@touryung 存下标每次访问也不需要多少性能 |
Beta Was this translation helpful? Give feedback.
-
每次找出的最大值构成一个只有root节点的树,那这些找出来的最大值做成的节点是怎么连成一棵树的呢? |
Beta Was this translation helpful? Give feedback.
-
@ 我太粗心了,漏掉了 root.left=递归函数(0,最大值下标) |
Beta Was this translation helpful? Give feedback.
-
大佬 YYDS |
Beta Was this translation helpful? Give feedback.
-
楼上那个超时的我也遇到了,是我以前copy别人的写法里面这个 buildTree(int[] preorder,int[] inorder){}方法的时候,这个preorder和inorder tmd反了,和测试样例正好参数反了。。 默认的是buildTree(int[] inorder, int[] postorder),我一直提交超时,以为自己写的有问题 真是日了狗了 |
Beta Was this translation helpful? Give feedback.
-
谢谢大佬!这里问题太绝了!
|
Beta Was this translation helpful? Give feedback.
-
点赞+1 |
Beta Was this translation helpful? Give feedback.
-
东哥,想问为什么还要计算leftSize。比如在106题中,postorder数组中,为啥不可以用index? root.left=self.build(inorder,inStart,index-1,postorder,postStart,index-1) |
Beta Was this translation helpful? Give feedback.
-
@hzy4211 这个 |
Beta Was this translation helpful? Give feedback.
-
想问一下在前、后那题里面,root.right build的时候是不是postEnd需要 -1 |
Beta Was this translation helpful? Give feedback.
-
前序与中序构建二叉树这里 TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
return traverse(preorder, inorder, 0, 0, preorder.size()-1);
}
//在inorder中找preorder中的元素
int findIndex(int elem, vector<int>& inorder){
for(int i = 0; i < inorder.size(); i++)
if(inorder[i] == elem)
return i;
return 0;
}
/**
pos——preooder中元素索引
l和h——inorder中子树区间
*/
TreeNode* traverse(vector<int>preorder, vector<int> inorder, int pos, int l, int h){
if(l > h) return nullptr;
int index;
for(int i = l; i <= h; i++){
index = findIndex(preorder[pos], inorder);
}
TreeNode* root = new TreeNode(preorder[pos]);
//左子树待构建的结点个数
int leftSize = index - pos;
root->left = traverse(preorder, inorder, pos + 1, l, index - 1);
root->right = traverse(preorder, inorder, pos + leftSize + 1, index + 1, h);
//后序位置
return root;
} 这里root->right总感觉有问题,但改不出来,有些测试能过,有些过不了,像[1,2,3],[2,3,1]就过不了,会报栈溢出 |
Beta Was this translation helpful? Give feedback.
-
前序中序构造二叉树不用新增数组的方法: class Solution:
def buildTree(self, preorder: List[int], inorder: List[int]) -> TreeNode:
if not preorder:
return None
rootvalue = preorder[0]
root = TreeNode(rootvalue)
leftsize = 0,0
for index in range(len(inorder)):
if inorder[index] == rootvalue:
leftsize = index
break
root.left = self.buildTree(preorder[1:leftsize+1],inorder[:index])
root.right = self.buildTree(preorder[leftsize+1:],inorder[index+1:])
return root |
Beta Was this translation helpful? Give feedback.
-
为什么只有前后序的时候需要判断preStart == preEnd的情况,而前中序和后中序不需要单独写这个判断呢? |
Beta Was this translation helpful? Give feedback.
-
|
Beta Was this translation helpful? Give feedback.
-
打卡 |
Beta Was this translation helpful? Give feedback.
-
基于先序和中序的构造也可以这么写,逻辑上和大佬的思路是一样的。 class Solution(object):
def buildTree(self, preorder, inorder):
"""
:type preorder: List[int]
:type inorder: List[int]
:rtype: TreeNode
"""
index_map = {k: idx for idx, k in enumerate(inorder)}
def build(left, right):
if left >= right: return None
node = TreeNode(preorder.pop(0))
node.left = build(left, index_map[node.val])
node.right = build(index_map[node.val]+1, right)
return node
return build(0, len(inorder)) |
Beta Was this translation helpful? Give feedback.
-
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* };
*/
struct TreeNode* buildTree(int* preorder, int preorderSize, int* inorder, int inorderSize)
{
if(preorderSize == 0 || inorderSize == 0)
return NULL;
struct TreeNode *tree = (struct TreeNode *)malloc(sizeof(struct TreeNode));
int elem = preorder[0];
int index = 0;
while(inorder[index] != elem)
index++;
tree->val = elem;
tree->left = buildTree(preorder + 1, index, inorder, index);
tree->right = buildTree(preorder + index + 1, preorderSize - index - 1, inorder + index + 1, inorderSize - index - 1);
return tree;
} |
Beta Was this translation helpful? Give feedback.
-
打卡 |
Beta Was this translation helpful? Give feedback.
-
东哥,“后文 二叉树就那几个框架”的链接貌似错了,直接在这个网站搜索也搜不到这篇文章。 |
Beta Was this translation helpful? Give feedback.
-
打卡 |
Beta Was this translation helpful? Give feedback.
-
20230114 打卡 |
Beta Was this translation helpful? Give feedback.
-
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
# valToIndex = {}
class Solution:
def buildTree(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]:
# i = 0
# for _ in inorder:
# valToIndex[_] = i
# i+=1
return self.build(preorder, inorder, 0, len(preorder)-1, 0, len(inorder)-1)
# build 函数的定义:
# 若前序遍历数组为 preorder[preStart..preEnd],
# 中序遍历数组为 inorder[inStart..inEnd],
# 构造二叉树,返回该二叉树的根节点
def build(self, preorder, inorder, preStart, preEnd, inStart, inEnd):
# inStart, inEnd: inorder 的开始和结束
# preStart, preEnd: preorder 的开始和结束
# base case
if preStart > preEnd:
return None
# root 节点对应的值就是前序遍历数组的第一个元素
rootval = preorder[preStart]
# rootVal 在中序遍历数组中的索引
# index = valToIndex.get(rootval)
index = inorder.index(rootval)
leftSize = index - inStart
root = ListNode(rootval)
# 分解到左右子树
root.left = self.build(preorder, inorder, preStart+1, preStart + leftSize, inStart, index-1 )
root.right = self.build(preorder, inorder,preStart+ leftSize+1 ,preEnd, index + 1, inEnd)
return root |
Beta Was this translation helpful? Give feedback.
-
中序和后序遍历那题 是怎么想到要做这个判断的呢,想不明白 |
Beta Was this translation helpful? Give feedback.
-
请问这里的build函数的base case为什么只用比较一个的start和end?不是传入了两对嘛? |
Beta Was this translation helpful? Give feedback.
-
请问各位大佬一个问题,为什么前序和后序构造二叉树的时候多了这个判断? |
Beta Was this translation helpful? Give feedback.
-
python 总结一下三种构造方式,需要注意的是从前序后序恢复二叉树结构时,不仅指定了root,同时指定了左节点,因此在计算递归索引过程中,是左节点的索引:index+1,再加上指定的根节点是首位,因此在前序排列中左子树的索引为1 : index+2 根据前序中序恢复二叉树结构 class Solution:
def buildTree(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]:
if not (preorder or inorder):
return None
root = TreeNode(preorder[0])
index = inorder.index(preorder[0])
root.left = self.buildTree(preorder[1:index+1], inorder[:index])
root.right = self.buildTree(preorder[index+1:], inorder[index+1:])
return root 根据后序中序恢复二叉树结构 class Solution:
def buildTree(self, inorder: List[int], postorder: List[int]) -> Optional[TreeNode]:
if not (inorder or postorder):
return None
root = TreeNode(postorder[-1])
index = inorder.index(postorder[-1])
root.left = self.buildTree(inorder[:index], postorder[:index])
root.right = self.buildTree(inorder[index+1:], postorder[index:-1])
return root 根据前序后续恢复二叉树结构 class Solution:
def constructFromPrePost(self, preorder: List[int], postorder: List[int]) -> Optional[TreeNode]:
if not(preorder and postorder):
return None
root = TreeNode(postorder[0])
# 若二叉树只有一个节点,直接返回根节点
if len(preorder) == 1:
return root
leftVal = preorder[1]
# 与前面两种构造不同的是,这里的索引是左节点索引,而非根节点索引
index = postorder.index(leftVal)
root.left = self.constructFromPrePost(preorder[1:index+2], postorder[:index+1])
root.right = self.constructFromPrePost(postorder[index+2:], postorder[index+1:-1]) |
Beta Was this translation helpful? Give feedback.
-
有一个小问题,为什么base case中只需要判断一组start和end,而不是if (preStart>preEnd | | inStart>inEnd)呢,有没有uu回答一下555 |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
文章链接点这里:东哥带你刷二叉树(构造篇)
评论礼仪 见这里,违者直接拉黑。
Beta Was this translation helpful? Give feedback.
All reactions