代码随想录算法训练营第十四天
LeetCode题目:
- 513. 找树左下角的值
- 112. 路径总和
- 106. 从中序与后序遍历序列构造二叉树
其他:
今日总结
往期打卡
513. 找树左下角的值
跳转: 513. 找树左下角的值
学习: 代码随想录公开讲解
问题:
给定一个二叉树的 根节点 root
,请找出该二叉树的 最底层 最左边 节点的值。
假设二叉树中至少有一个节点。
思路:
这题所有遍历都可以做,不过不用层序遍历至少需要传递节点的深度,在遍历某深度第一个左节点时存储遇到的第一个元素.这里选择使用模拟队列层序遍历
复杂度:
- 时间复杂度: O ( n ) O(n) O(n)
- 空间复杂度: O ( n ) O(n) O(n)
代码(层序遍历):
class Solution {
public int findBottomLeftValue(TreeNode root) {
TreeNode[] queue = new TreeNode[10000];
int h=0,t=0;
queue[0] = root;
int ans=0;
while(h<=t) {
int l = t;
ans = queue[h].val;
while(h<=l) {
TreeNode tmp = queue[h++];
if(tmp.left!=null) queue[++t]= tmp.left;
if(tmp.right!=null) queue[++t]= tmp.right;
}
}
return ans;
}
}
112. 路径总和
跳转: 112. 路径总和
学习: 代码随想录公开讲解
问题:
给你二叉树的根节点 root
和一个表示目标和的整数 targetSum
。判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 targetSum
。如果存在,返回 true
;否则,返回 false
。
叶子节点 是指没有子节点的节点。
思路:
这题就不太好用层序遍历了,不然要维护多路径
使用前序中序后序遍历均可,只要加上对叶子节点的判断即可
非递归实现是用栈
这里选择使用前序递归遍历
复杂度:
- 时间复杂度: O ( n ) O(n) O(n)
- 空间复杂度: O ( l o g n ) O(logn) O(logn)(平均,最坏为n层栈)
代码:
class Solution {
boolean handle(TreeNode root,int sum,int targetSum){
if(root==null) return false;
if(root.left==null&&root.right==null){
return (sum+root.val)==targetSum;
}
boolean a = handle(root.left,sum+root.val,targetSum);
if(a) return true;
return handle(root.right,sum+root.val,targetSum);
}
public boolean hasPathSum(TreeNode root, int targetSum) {
return handle(root,0,targetSum);
}
}
106. 从中序与后序遍历序列构造二叉树
跳转: 106. 从中序与后序遍历序列构造二叉树
学习: 代码随想录公开讲解
问题:
给定两个整数数组 inorder
和 postorder
,其中 inorder
是二叉树的中序遍历, postorder
是同一棵树的后序遍历,请你构造并返回这颗 二叉树 。
思路:
后序遍历和先序遍历都可以知道头节点的值,中序遍历可以分割左右子树,所以知道了后序或前序之一以及中序遍历的顺序,就可以不断分割数组构造二叉树.
分割数组建议使用索引而不是复制数组,因为复制操作效率不高还占空间.
复杂度:
代码(索引哈希):
class Solution {
Map<Integer, Integer> map;
public TreeNode getTree(int[] inorder, int[] postorder, int inStart, int inEnd, int postStart, int postEnd) {
if (inStart == inEnd)
return null;
TreeNode root = new TreeNode(postorder[postEnd - 1]);
if (inEnd - inStart == 1)
return root;
int i = map.get(postorder[postEnd-1])-inStart;
while (inorder[inStart + i] != postorder[postEnd - 1]) {
i++;
}
root.left = getTree(inorder, postorder, inStart, inStart + i, postStart, postStart + i);
root.right = getTree(inorder, postorder, inStart + i + 1, inEnd, postStart + i, postEnd - 1);
return root;
}
public TreeNode buildTree(int[] inorder, int[] postorder) {
map = new HashMap<>();
for (int i = 0; i < inorder.length; i++) {
map.put(inorder[i], i);
}
int n = inorder.length;
return getTree(inorder, postorder, 0, n, 0, n);
}
}
代码(查找索引):
class Solution {
public TreeNode getTree(int[] inorder, int[] postorder,int inStart,int inEnd,int postStart,int postEnd){
if(inStart==inEnd) return null;
TreeNode root = new TreeNode(postorder[postEnd-1]);
if(inEnd-inStart==1) return root;
int i = 0;
while(inorder[inStart+i]!=postorder[postEnd-1]){
i++;
}
root.left = getTree(inorder,postorder,inStart,inStart+i,postStart,postStart+i);
root.right = getTree(inorder,postorder,inStart+i+1,inEnd,postStart+i,postEnd-1);
return root;
}
public TreeNode buildTree(int[] inorder, int[] postorder) {
int n = inorder.length;
return getTree(inorder,postorder,0,n,0,n);
}
}
代码(复制数组):
class Solution {
public TreeNode buildTree(int[] inorder, int[] postorder) {
int n = postorder.length;
if (n == 0)
return null;
TreeNode root = new TreeNode(postorder[n - 1]);
if (n == 1)
return root;
int i = 0;
while (inorder[i] != postorder[n-1]) {
i++;
}
if (i > 0) {
int[] leftPost = Arrays.copyOfRange(postorder, 0, i);
int[] leftIn = Arrays.copyOfRange(inorder, 0, i);
root.left = buildTree(leftIn, leftPost);
}
if (i < n - 1) {
int[] rightPost = Arrays.copyOfRange(postorder, i, n-1);
int[] rightIn = Arrays.copyOfRange(inorder, i+1, n);
root.right = buildTree(rightIn, rightPost);
}
return root;
}
}
总结
今日继续练习二叉树遍历,练习了中序+前/后序构造二叉树
往期打卡
代码随想录算法训练营第十三天
代码随想录算法训练营第十二天
代码随想录算法训练营第十一天
代码随想录算法训练营周末二
代码随想录算法训练营第十天
代码随想录算法训练营第九天
代码随想录算法训练营第八天
代码随想录算法训练营第七天
代码随想录算法训练营第六天
代码随想录算法训练营第五天
代码随想录算法训练营周末一
代码随想录算法训练营第四天
代码随想录算法训练营第三天
代码随想录算法训练营第二天
代码随想录算法训练营第一天