513.找树左下角的值
本题很明显用层次遍历是最简单的:
class Solution {
public int findBottomLeftValue(TreeNode root) {
List<List<Integer>> res=Order(root);//获得层次遍历序列
//取出最下面一层
List<Integer> lastlayer=res.get(res.size()-1);
int leftvalue=lastlayer.get(0);
return leftvalue;
}
//得到二叉树层序遍历的数组
public List<List<Integer>> Order(TreeNode root){
if(root==null){
return null;
}
List<List<Integer>> resList=new ArrayList<>();
Queue<TreeNode> q=new LinkedList<>();
q.offer(root);
while(!q.isEmpty()){
int len=q.size();
List<Integer> list=new ArrayList<>();
while(len>0){
TreeNode node=q.poll();//从队列取出头元素
list.add(node.val);
if(node.left!=null){
q.offer(node.left);
}
if(node.right!=null){
q.offer(node.right);
}
len--;
}
resList.add(list);
}
return resList;
}
}
112.路径总和
本题应该是一个深度优先遍历的过程,然后在最后的叶子结点回溯一下。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public boolean hasPathSum(TreeNode root, int targetSum) {
if(root==null){
return false;
}
//如果是叶子结点,判断,target值从根节点一路减下来,和当前值是否相等
if(root.left==null&&root.right==null){
return targetSum == root.val;
}
if(root.left!=null){
//往左子树找
boolean left=hasPathSum(root.left, targetSum-root.val);
if (left) {
return true;//找到
}
}
if(root.right!=null){
//往右子树找
boolean right=hasPathSum(root.right, targetSum-root.val);
if (right) {
return true;//找到
}
}
return false;
}
}
113.路径总和2
给定一个二叉树和一个目标和,找到所有从根节点到叶子节点路径总和等于给定目标和的路径。
说明: 叶子节点是指没有子节点的节点。
示例: 给定如下二叉树,以及目标和 sum = 22,
106.从中序与后序遍历序列构造二叉树
正常手写构造二叉树的过程
中序:9 3 15 20 7
后序:9 15 7 20 3
后序遍历的最后一个结点就是根节点3。在中序遍历里找到这个结点划分左右,3的右边就是右子树,左边就是左子树,本题里中序里的3的左边只有9,3的右边有15,20,7,这就是组成右子树的结点。
再从后序:15 7 20中得出,20就是右子树的根结点。中序15 20 7,那么15就是20的左孩子,7就是20的右孩子。
思路:递归
- 判断数组是否为空。
- 取出postorder的最后一个作为结点元素
- 切割中序,切成左和右。
- 切割后序,切成后序左和右。
- 递归处理左区间,又区间。
重要的点,就是中序数组大小一定是和后序数组的大小相同的
确定切割的标准:遵循左闭右开原则 :[ )
分析:单层的切割逻辑
切左边:
- rootIndex:当前的中序里根的位置
这边切一刀,实际上就是rootIndex-inBegin=1-0=1,左子树的个数是1。
根据这个去切后序,后序的左也要和中序的个数保持一致。
leftpostend:后序左子树的终止,postBegin+lenOfLeft.
新的中序和后序就产生了。
切右边: - 中序的begin就是rootindex下一个下标,inEnd还是inEnd,不变。
- 后序的rightBegin=postBegin+lenOfLeft;
- 后序的eng就是原来的end-1(减去作为root的那个结点)
//切割后序的右子树
int rightpostBegin=postBegin+lenOfLeft;
int rightpostEnd=postEnd-1;
newroot.right=findNode(inorder,rootIndex+1,inEnd,postorder,rightpostBegin,rightpostEnd);//建立右子树
//根据rootIndex切割中序序列
int lenOfLeft=rootIndex-inBegin;//左子树应该有的结点个数。
//根据中序左子树去切后序的左子树
int leftpostEnd=postBegin+lenOfLeft;
newroot.left=findNode(inorder,inBegin,rootIndex,postorder,postBegin,leftpostEnd);//建立左子树
class Solution{
Map<Integer, Integer> map; // 方便根据数值查找位置
public TreeNode buildTree(int[] inorder, int[] postorder) {
map = new HashMap<>();
for(int i=0;i<inorder.length;i++){
map.put(inorder[i],i);//保存中序序列的值和对应的下标。
}
return findNode(inorder,0,inorder.length,postorder,0,postorder.length);
}
/**
*
* @param inorder 中序遍历序列
* @param inBegin 中序起始
* @param inEnd 中序截至
* @param postorder 后序序列
* @param postBegin 后起
* @param postEnd 后止
* @return
*/
public TreeNode findNode(int[] inorder,int inBegin,int inEnd,int[] postorder,int postBegin,int postEnd){
if(inBegin>=inEnd||postBegin>=postEnd){
return null;
}
//找到后序遍历的最后一个结点,作为当前的根节点
int root=postorder[postEnd-1];//后序遍历最后一个元素
//找到这个根节点在中序中的位置。
int rootIndex=map.get(root);
//新建结点
TreeNode newroot=new TreeNode(inorder[rootIndex]);
//根据rootIndex切割中序序列
int lenOfLeft=rootIndex-inBegin;//左子树应该有的结点个数。
//根据中序左子树去切后序的左子树
int leftpostEnd=postBegin+lenOfLeft;
newroot.left=findNode(inorder,inBegin,rootIndex,postorder,postBegin,leftpostEnd);//建立左子树
//切割后序的右子树
int rightpostBegin=postBegin+lenOfLeft;
int rightpostEnd=postEnd-1;
newroot.right=findNode(inorder,rootIndex+1,inEnd,postorder,rightpostBegin,rightpostEnd);//建立右子树
return newroot;
}
}