1、题目1:513-找树左下角的值
给定一个二叉树的 根节点
root
,请找出该二叉树的 最底层 最左边 节点的值。假设二叉树中至少有一个节点。
思路:
层序遍历简单,从右边往左边迭代即可
public int findBottomLeftValue(TreeNode root) {
LinkedList<TreeNode> queue = new LinkedList<>();
if(root == null){
return 0;
}
int val = 0;
queue.offer(root);
while (!queue.isEmpty()){
int size = queue.size();
while (size-- >0){
TreeNode node = queue.pop();
val = node.val;
if(node.right!=null){
queue.offer(node.right);
}
if(node.left !=null){
queue.offer(node.left);
}
}
}
return val;
}
2、题目2:112-路径总和
给你二叉树的根节点
root
和一个表示目标和的整数targetSum
。判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和targetSum
。如果存在,返回true
;否则,返回false
。叶子节点 是指没有子节点的节点。
输入: root = [5,4,8,11,null,13,4,7,2,null,null,null,1], targetSum = 22 输出: true 解释: 等于目标和的根节点到叶节点路径如上图所示。
思路:类似前面的打印路径
public static boolean hasPathSum(TreeNode root, int targetSum) {
HashSet<Integer> set = new HashSet<>();
if(root == null){
return false;
}
ArrayList<Integer> list = new ArrayList<>();
getSum(root,set,list);
return set.contains(targetSum)?true:false;
}
public static void getSum(TreeNode node,HashSet<Integer> set,ArrayList<Integer> list){
list.add(node.val);
// 碰到叶子节点要回溯下
if(node.left == null && node.right ==null){
int sum = list.stream().mapToInt(Integer::intValue).sum();
set.add(sum);
}
if(node.left !=null){
getSum(node.left,set,list);
// 回溯
list.remove(list.size()-1);
}
if(node.right !=null){
getSum(node.right,set,list);
// 回溯
list.remove(list.size()-1);
}
}
3、题目3:113-路径总和II
给你二叉树的根节点
root
和一个整数目标和targetSum
,找出所有 从根节点到叶子节点 路径总和等于给定目标和的路径。叶子节点 是指没有子节点的节点。
输入: root = [5,4,8,11,null,13,4,7,2,null,null,5,1], targetSum = 22 输出: [[5,4,11,2],[5,8,4,5]]
思路,掌握递归三部曲即可
public static List<List<Integer>> pathSum(TreeNode root, int targetSum) {
List<List<Integer>> list = new ArrayList();
if(root == null){
return list;
}
ArrayList<Integer> paths = new ArrayList<>();
getSameValue(root,targetSum,paths,list);
return list;
}
static void getSameValue(TreeNode node,int targeSum,ArrayList<Integer> paths,List<List<Integer>> res){
paths.add(node.val);
// 到根节点算是完成一条路径,需要取出这条路径进行比对
if(node.left == null && node.right == null){
int sum=0;
for (Integer path : paths) {
sum+=path;
}
if(sum == targeSum){
res.add(new ArrayList<>(paths));
}
}
if(node.left !=null){
getSameValue(node.left,targeSum,paths,res);
paths.remove(paths.size()-1);
}
if(node.right !=null){
getSameValue(node.right,targeSum,paths,res);
paths.remove(paths.size()-1);
}
}
4、题目4:106-从中序与后序遍历序列构造二叉树
给定两个整数数组 inorder
和 postorder
,其中 inorder
是二叉树的中序遍历, postorder
是同一棵树的后序遍历,请你构造并返回这棵 二叉树 。
输入: inorder = [9,3,15,20,7], postorder = [9,15,7,20,3] 输出: [3,9,20,null,null,15,7]
思路:
1、后序数组为空,空节点
2、后续数组最后一个元素为节点元素
3、寻找中序数组位置作为切割点
4、切中序位置,切成中序左数组和中序右数组
5、切后序位置,切成后序左数组和后序右数组
6、递归处理左区间和右区间
递归三部曲:
1、入参返回
TreeNode traver(int[] pre ,int[] end){
}
2、结束逻辑
if(end.size ==0) return null;
rootVal = end(end.size()-1)//后序最后一个
TreeNode root = new TreeNode(rootVal );
if(root.size==1) return root;
3、单层递归逻辑
// 第三步:找切割点
int delimiterIndex;
for (delimiterIndex = 0; delimiterIndex < inorder.size(); delimiterIndex++) {
if (inorder[delimiterIndex] == rootValue) break;
}
// 第四步:切割中序数组,得到 中序左数组和中序右数组
// 第五步:切割后序数组,得到 后序左数组和后序右数组
// 第六步
root->left = traversal(中序左数组, 后序左数组);
root->right = traversal(中序右数组, 后序右数组);
为什么要切割中序数组呢?
切割点在后序数组的最后一个元素,就是用这个元素来切割中序数组的,所以必要先切割中序数组。
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); // 前闭后开
}
private TreeNode findNode(int[] inorder, int inBegin, int inEnd, int[] postorder, int postBegin, int postEnd) {
//左闭右开
if(inBegin >= inEnd || postBegin >= postEnd){
return null;
}
// 找到后序遍历的最后一个元素在中序遍历中的位置
int rootIndex = map.get(postorder[postEnd - 1]);
TreeNode root = new TreeNode(inorder[rootIndex]); // 构造结点
int lenOfLeft = rootIndex - inBegin; // 保存中序左子树个数,用来确定后序数列的个数
root.left = findNode(inorder, inBegin, rootIndex,
postorder, postBegin, postBegin + lenOfLeft);
root.right = findNode(inorder, rootIndex + 1, inEnd,
postorder, postBegin + lenOfLeft, postEnd - 1);
return root;
}