# lettcode algorithm problem punch in - day05

Keywords: Java C++ data structure

## Maximum depth of binary tree

Given a binary tree, find its maximum depth. The depth of the binary tree is the number of nodes on the longest path from the root node to the farthest leaf node.

explain:   A leaf node is a node that has no children.

Example:
Given binary tree [3,9,20,null,null,15,7],

3
/ \
9  20
/  \
15   7

Returns its maximum depth   3 .

## Idea:

### Method 1: depth first search

If we know the maximum depth of the left subtree and the right subtree   ll   and   rr, then the maximum depth of the binary tree is max(l,r)+1

public int maxDepth(TreeNode root) {
if(root == null){
return 0;
}else{
int leftHeight = maxDepth(root.left);
int rightHeight = maxDepth(root.right);
return Math.max(leftHeight,rightHeight) + 1;
}
}

Complexity analysis

Time complexity: O(n)O(n), where nn is the number of binary tree nodes. Each node is traversed only once in recursion.

Spatial complexity: O(\textit{height})O(height), where \ textit{height}height represents the height of the binary tree. Recursive functions need stack space, which depends on the depth of recursion, so the space complexity is equivalent to the height of binary tree.

### Method 2: breadth first search

We can also use "breadth first search" to solve this problem, but we need to make some modifications. At this time, our breadth first search queue stores "all nodes of the current layer". Each time we expand the next layer, unlike breadth first search, which only takes out one node from the queue at a time, we need to take out all nodes in the queue for expansion, so as to ensure that all nodes of the current layer are stored in the queue after each expansion, that is, we expand layer by layer, Finally, we use a variable ans to maintain the number of extensions. The maximum depth of the binary tree is ANS.

class Solution {
public int maxDepth(TreeNode root) {
if (root == null) {
return 0;
}
queue.offer(root);
int ans = 0;
while (!queue.isEmpty()) {
int size = queue.size();
while (size > 0) {
TreeNode node = queue.poll();
if (node.left != null) {
queue.offer(node.left);
}
if (node.right != null) {
queue.offer(node.right);
}
size--;
}
ans++;
}
return ans;
}
}


Complexity analysis

Time complexity: O(n)O(n), where nn is the number of nodes of the binary tree. In the same analysis as method 1, each node is accessed only once.

Space complexity: the space consumption of this method depends on the number of elements stored in the queue, which will reach O(n)O(n) in the worst case.

# Validate binary search tree

Give you the root node of a binary tree, root, to determine whether it is an effective binary search tree.

A valid binary search tree is defined as follows:

The left subtree of a node contains only a number smaller than the current node.
The right subtree of a node contains only a number greater than the current node.
All left and right subtrees themselves must also be binary search trees.

Example 1:

Input: root = [2,1,3]
Output: true

Example 2:

Input: root = [5,1,4,null,null,3,6]
Output: false
Explanation: the value of the root node is 5, but the value of the right child node is 4.

## Idea:

### Method 1: recursion

We design a recursive function helper(root, lower, upper) to recursively judge. The function indicates that the subtree with root as the root is considered to judge whether the values of all nodes in the subtree are within the range of (l,r)(l,r) (note that it is an open interval). If the value val of the root node is not within the range of (l,r)(l,r), it indicates that it does not meet the conditions and returns directly. Otherwise, we need to continue the recursive call to check whether its left and right subtrees are satisfied. If they are satisfied, it indicates that this is a binary search tree.

Then, according to the nature of the binary search tree, when recursively calling the left subtree, we need to change the upper bound to root.val, that is, call helper(root.left, lower, root.val), because the values of all nodes in the left subtree are less than those of its root node. Similarly, when calling the right subtree recursively, we need to change the lower bound to root.val, that is, call helper(root.right, root.val, upper).

class Solution {
public:
bool helper(TreeNode* root, long long lower, long long upper) {
if (root == nullptr) {
return true;
}
if (root -> val <= lower || root -> val >= upper) {
return false;
}
return helper(root -> left, lower, root -> val) && helper(root -> right, root -> val, upper);
}
bool isValidBST(TreeNode* root) {
return helper(root, LONG_MIN, LONG_MAX);
}
};


### Sequence traversal in method 2

During the middle order traversal, judge whether the current node is greater than the previous node of the middle order traversal. If greater than, it means that the BST is met and continue the traversal; Otherwise, false is returned directly.

class Solution {
long pre = Long.MIN_VALUE;
public boolean isValidBST(TreeNode root) {
if (root == null) {
return true;
}
// Access left subtree
if (!isValidBST(root.left)) {
return false;
}
// Accessing the current node: if the current node is less than or equal to the previous node traversed in the middle order, it indicates that the BST is not satisfied, and false is returned; Otherwise, continue traversal.
if (root.val <= pre) {
return false;
}
pre = root.val;
// Access right subtree
return isValidBST(root.right);
}
}



Primary algorithm - LeetBook - LeetCode, the technology growth platform loved by geeks around the world (leetcode-cn.com)

Posted by riwan on Sun, 28 Nov 2021 08:52:54 -0800