Leetcode 513. 找树左下角的值
思路:这道题要再最后一行 找到最左边的值, 第一反应是用BFS, 遍历每一行都记录第一个值,那么最后一个值就是树左下角的值
class Solution {
public int findBottomLeftValue(TreeNode root) {
//bfs
Queue<TreeNode> queue = new ArrayDeque<>();
int ans = -1;
if(root != null){
queue.offer(root);
}
while( !queue.isEmpty()){
int size = queue.size();
for (int i = 0; i < size; i++ ){
TreeNode node = queue.poll();
if(i == 0){
ans = node.val;
}
if(node.left != null){
queue.offer(node.left);
}
if(node.right != null){
queue.offer(node.right);
}
}
}
return ans;
}
}
使用递归法,在递归过程中要确定深度,并找到最左边的叶子。高度的确定使用一个全局变量,记录最大深度。还需要一个全局变量记录最大深度最左节点的数值。每递归到下一层,最大深度值都会更新,不论使用什么遍历,只要保证先左后右的顺序,第一次更新最大深度时,访问的节点就是该层最左的节点,记录该节点的值。之后虽然会访问同层的其他节点,但是最大深度不再更新,其他节点的值不会被记录。
class Solution {
int maxDepth = Integer.MIN_VALUE;
int ans;
public int findBottomLeftValue(TreeNode root) {
dfs(root, 0);
return ans;
}
private void dfs(TreeNode root, int depth){
if(depth > maxDepth){
maxDepth = depth;
ans = root.val;
}
if(root.left != null){
dfs(root.left, depth + 1);
}
if(root.right != null){
dfs (root.right, depth + 1);
}
}
}
112. 路径总和
112 和113 非常类似,区别在于在遇到leaf 时,进行不同的处理。 递归搭配回溯,比较经典的运用
class Solution {
public boolean hasPathSum(TreeNode root, int targetSum) {
if(root == null) {
return false;
}
if(root.left == null && root.right == null){
return targetSum == root.val;
}
return hasPathSum(root.left, targetSum - root.val) ||
hasPathSum(root.right, targetSum - root.val);
}
}
113. 路径总和ii
class Solution {
public List<List<Integer>> pathSum(TreeNode root, int targetSum) {
List<List<Integer>> res = new ArrayList<>();
if(root == null) return res;
List<Integer> path = new ArrayList<>();
dfs(root, targetSum, res, path);
return res;
}
private void dfs(TreeNode root, int targetSum, List<List<Integer>> res, List<Integer> path){
path.add(root.val);
if(root.left == null && root.right == null){
if(targetSum == root.val ){
res.add(new ArrayList<>(path));
}
}
if(root.left != null){
dfs(root.left, targetSum - root.val, res, path);
}
if(root.right != null){
dfs(root.right, targetSum - root.val, res, path);
}
path.remove(path.size() - 1);
}
}
106.从中序与后序遍历序列构造二叉树
先用中序和后序数组把二叉树画出来,发现后序数组的最后一个元素是root,通过这个root我们能在中序数组中把左子树和右子树分隔出来,然后用递归处理左子树和右子树。
具体的步骤:
1. 如果数组为空, return null
2. 如果数组不为空,取后序数组最后一个元素为root
3. 以root为切割点,将中序数组分成中序左树数组和中序右树数组
因为数组里元素不重复,所以可以用二分法找到root,或者用HashMap 储存元素和下标,可以以O(1)找到root。
4. 按照中序左树数组和中序右树数组的长度,将后序数组切割
5. 递归处理左数组和右数组
class Solution {
public TreeNode buildTree(int[] inorder, int[] postorder) {
HashMap<Integer, Integer> record = new HashMap<>();
for(int i = 0; i < inorder.length; i++ ){
record.put(inorder[i], i);
}
return buildTree(inorder, 0, inorder.length -1, postorder, 0, postorder.length - 1, record);
}
//左闭右闭
private TreeNode buildTree(int[] inorder, int inLeft, int inRight, int[] postorder,int postLeft, int postRight, HashMap<Integer, Integer> record){
if(inLeft > inRight || postLeft > postRight){
return null;
}
int rootVal = postorder[postRight];
int idxRoot = record.get(rootVal);
int leftSize = idxRoot - inLeft;
TreeNode left = buildTree(inorder, inLeft, idxRoot - 1,postorder, postLeft, postLeft + leftSize - 1,record);
TreeNode right = buildTree(inorder,idxRoot + 1, inRight, postorder,postLeft + leftSize, postRight - 1 ,record);
return new TreeNode(rootVal, left, right);
}
}
105.从前序与中序遍历序列构造二叉树
与106思路一样,只是root的值来自于preorder数组的第一个值
class Solution {
public TreeNode buildTree(int[] preorder, int[] inorder) {
Map<Integer, Integer> record = new HashMap<>();
for(int i = 0; i < inorder.length; i++){
record.put(inorder[i], i);
}
return buildTree(preorder, 0, 0, inorder.length - 1, record);
}
private TreeNode buildTree(int[] preorder,int m, int inLeft, int inRight, Map<Integer, Integer> record ){
if(inLeft > inRight) {
return null;
}
int midVal = preorder[m];
int mid = record.get(midVal);
TreeNode left = buildTree(preorder, m + 1, inLeft, mid - 1,record);
TreeNode right = buildTree(preorder, m + 1 + mid -inLeft, mid + 1, inRight,record);
return new TreeNode(midVal, left, right);
}
}
376



被折叠的 条评论
为什么被折叠?



