515. Find Largest Value in Each Tree Row

1. Description

Given the root of a binary tree, return an array of the largest value in each row of the tree (0-indexed).

2. Example

Example 1:
Input: root = [1,3,2,5,3,null,9]
Output: [1,3,9]

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

Example 3:
Input: root = [1]
Output: [1]

Example 4:
Input: root = [1,null,2]
Output: [1,2]

Example 5:
Input: root = []
Output: []

3. Constraints

  • The number of nodes in the tree will be in the range [0, $10^4$].
  • $-2^{31}$ <= Node.val <= $2^{31} - 1$

4. Solutions

My Accepted Solution

n is the number of nodes in i_root
Time complexity: O(n)
Space complexity: O(n)

class Solution 
{
private:
    int maxDepth = -1;
    vector<int> largestValueAtLevel = vector<int>(10000, INT_MIN);
    // if we use map, we have to judge whether the key is existed, I don't know its time complexity
    // but if we use vector, it will take up O(n) space complexity, while the recursion will also take O(n)
    // so it will not affect the whole spave complexity
    
    void preorderTraverse(TreeNode *i_root, int depth)
    {
        maxDepth = max(maxDepth, depth);
        largestValueAtLevel[depth] = max(largestValueAtLevel[depth], i_root->val);
        
        if(i_root->left) preorderTraverse(i_root->left, depth + 1);
        if(i_root->right) preorderTraverse(i_root->right, depth + 1);
    } 
public:
    // vector<int> largestValues(TreeNode* root)
    vector<int> largestValues(TreeNode *i_root) 
    {
        if(!i_root) return vector<int>{};
        
        preorderTraverse(i_root, 0);
        
        vector<int> result(maxDepth + 1);
        for(int i = 0; i <= maxDepth; i++)
        {
            result[i] = largestValueAtLevel[i];
        }
        
        return result;
    }
};

4.1 Breadth-first Search && Level Iteration

n is the number of nodes in i_root
Time complexity: O(n)
Space complexity: O(n)

class Solution 
{
public:
    // vector<int> largestValues(TreeNode* root)
    vector<int> largestValues(TreeNode *i_root) 
    {
        if(!i_root) return vector<int>{};
        
        vector<int> result; 
        queue<const TreeNode *> currentLevelNodes{{i_root}};
        queue<const TreeNode *> nextLevelNodes;
        
        int maxLevelValue = INT_MIN;
        while(!currentLevelNodes.empty() || !nextLevelNodes.empty())
        {
            if(currentLevelNodes.empty())
            {                       
                swap(currentLevelNodes, nextLevelNodes);  
                result.push_back(maxLevelValue);
                
                maxLevelValue = INT_MIN;
            }
            else
            {
                auto node = currentLevelNodes.front();
                currentLevelNodes.pop();
                
                maxLevelValue = max(maxLevelValue, node->val);
                
                if(node->left) nextLevelNodes.push(node->left);
                if(node->right) nextLevelNodes.push(node->right);
            }
        }
        
        result.push_back(maxLevelValue);
        
        return result;
    }
};

4.2 Morris Traversal

Morris Traversal
神级遍历——morris

n is the number of nodes in i_root
Time complexity: O(n)
Space complexity: O(n)

// the algorithm's space complexity is O(1), but we have use a vector to return, so we think the total space complexity is O(n)
// on the other hand, to better describe the complexity, we could ignore the required complexity like the space taken by the answer

// all iteration methords could use morris rather than recursion or level iteration
// but this methord it pretty hard
// and the time complexity is more imprtant than space complexity

// The process of Morris Traversal
// 1. if current node doesn't have a left child, go right
// 2. if current node have a left child, find its most right node
//      3.1 if the most right node's right pointer is nullptr, let it point to the current node and go left
//      3.2 if the most right node's right pointer points to the current node, let it be nullptr and go right

// case 3.1 and 3.2 actually means whether or not we have iterated the left node
// the reason why we find the left child's most right node is in the preorder, the next node of that one is the current node
// so this is a methord to return back to the parent node without using a stack

class Solution 
{
public:
    // vector<int> largestValues(TreeNode* root)
    vector<int> largestValues(TreeNode *i_root) 
    {
        vector<int> result;
        TreeNode *currentNode = i_root, *previousNode = nullptr;
        int depth = 0;
        while(currentNode)
        {
            if(!currentNode->left) // case 1, go left
            {
                if(depth >= result.size()) result.push_back(currentNode->val);
                else result[depth] = max(result[depth], currentNode->val);
                
                depth++;
                currentNode = currentNode->right;
            }
            else 
            {
                previousNode = currentNode->left; // case 2, let previousNode be currentNode->left, then find the most right node
                
                int moveSteps = 1;
                while(previousNode->right && previousNode->right != currentNode)
                {
                    previousNode = previousNode->right;
                    moveSteps++;
                }
                
                if(!previousNode->right)
                {
                    if(depth >= result.size()) result.push_back(currentNode->val);
                    
                    previousNode->right = currentNode;
                    currentNode = currentNode->left;
                    depth++;
                }
                else
                {
                    previousNode->right = nullptr;
                    depth -= moveSteps + 1;
                    
                    if(depth >= result.size()) result.push_back(currentNode->val);
                    else result[depth] = max(result[depth], currentNode->val);
                    
                    currentNode = currentNode->right;
                    depth++;
                }
            }
        }
        
        return result;
    }
};
comments powered by Disqus