Monday, September 26, 2022

[LeetCode] Find Bottom Left Tree Value

Problem: Given the root of a binary tree, return the leftmost value in the last row of the tree.

Example:

Input: root = [2,1,3]
Output: 1
Input: root = [1,2,3,4,null,5,6,null,null,7]
Output: 7


Approach: We can use Level Order Traversal here. Basically while doing level order traversal, we can store the first element of the current level in a variable which is basically the left most element of that particular level in the tree.

In that way when the traversal ends, we will have the left most element of the last level.


Implementation in C#:

    public int FindBottomLeftValue(TreeNode root) 

    {

        if (root == null)

        {

            return -1;

        }

        Queue<TreeNode> queue = new Queue<TreeNode>();

        queue.Enqueue(root);

        int leftMostValue = -1;

        while(queue.Count > 0)

        {

            int queueSize = queue.Count;

            for (int i = 0; i < queueSize; ++i)

            {

                TreeNode node = queue.Dequeue();

                if (i == 0)

                {

                    leftMostValue = node.val;

                }

                if (node.left != null)

                {

                    queue.Enqueue(node.left);

                }    

                if (node.right != null)

                {

                    queue.Enqueue(node.right);

                }

            }

        }

        return leftMostValue;

    }


Complexity: O(n)

[LeetCode] Most Frequent Subtree Sum

Problem: Given the root of a binary tree, return the most frequent subtree sum. If there is a tie, return all the values with the highest frequency in any order.

The subtree sum of a node is defined as the sum of all the node values formed by the subtree rooted at that node (including the node itself).

Example:

Input: root = [5,2,-3]
Output: [2,-3,4]

Input: root = [5,2,-5]
Output: [2]

Approach: We can use Preorder traversal here to solve this question. Approach is straight forward, can be understood easily by just looking at the implementation.


Implementation in C#:

    public int[] FindFrequentTreeSum(TreeNode root) 

    {

        if (root == null)

        {

            return null;

        }

        Dictionary<int, int> sumFreqMap = new Dictionary<int, int>();

        this.FindFrequentTreeSumPreOrder(root, sumFreqMap);

        HashSet<int> result = new HashSet<int>();

        int maxFreq = 0;

        foreach (var sumItem in sumFreqMap)

        {

            if (maxFreq < sumItem.Value)

            {

                result.Clear();

                result.Add(sumItem.Key);

                maxFreq = sumItem.Value;

            }

            else if (maxFreq == sumItem.Value)

            {

                result.Add(sumItem.Key);

            }

        }

        return result.ToArray();

    }

    

    public int FindFrequentTreeSumPreOrder(TreeNode node, Dictionary<int, int> sumFreqMap)

    {

        if (node == null)

        {

            return 0;

        }

        if (node.left == null && node.right == null)

        {

            if (!sumFreqMap.ContainsKey(node.val))

            {

                sumFreqMap[node.val]  = 0;

            }

            ++sumFreqMap[node.val];

            return node.val;

        }

        int leftSum = FindFrequentTreeSumPreOrder(node.left, sumFreqMap);

        int rightSum = FindFrequentTreeSumPreOrder(node.right, sumFreqMap);

        int subTreeSum = node.val + leftSum + rightSum;

        if (!sumFreqMap.ContainsKey(subTreeSum))

        {

            sumFreqMap[subTreeSum]  = 0;

        }

        ++sumFreqMap[subTreeSum];

        return subTreeSum;

    }


Complexity: O(n)

[LeetCode] Find Mode in Binary Search Tree

Problem: Given the root of a binary search tree (BST) with duplicates, return all the mode(s) (i.e., the most frequently occurred element) in it.

If the tree has more than one mode, return them in any order.

Assume a BST is defined as follows:

  • The left subtree of a node contains only nodes with keys less than or equal to the node's key.
  • The right subtree of a node contains only nodes with keys greater than or equal to the node's key.
  • Both the left and right subtrees must also be binary search trees.

Example:

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


Approach: A simple inorder traversal can work here as in case of BST, inorder traversal will give the output in sorted order. Just look at the implementation to understand it.


Implementation in C#:

    public int[] FindMode(TreeNode root) 

    {

        if (root == null)

        {

            return null;

        }      

        int max = 0;

        TreeNode prevNode = null;

        int prevFreq = 0;

        List<int> result = new List<int>();   

        this.FindModeInorder(root, ref prevNode, ref prevFreq, result, ref max);

        return result.ToArray();

    }

    

    private void FindModeInorder(TreeNode node,

                                ref TreeNode prevNode,

                                ref int prevFreq,

                                List<int> result,

                                ref int max)

    {

        if (node == null)

        {

            return;

        }

        this.FindModeInorder(node.left, ref prevNode, ref prevFreq, result, ref max);

        if (prevNode != null)

        {

            if (node.val == prevNode.val)

            {

                ++prevFreq;

            }

            else

            {

                prevFreq = 1;

            }

        }

        else

        {

            // Current node is the leftmost node

            ++prevFreq;

            max = prevFreq;

        }

        prevNode = node;

        if (prevFreq > max)

        {

            max = prevFreq;

            result.Clear();

            result.Add(node.val);

        }

        else if(prevFreq == max)

        {

            result.Add(node.val);

        }

        this.FindModeInorder(node.right, ref prevNode, ref prevFreq, result, ref max);

    }


Complexity: O(n)

Friday, September 23, 2022

[LeetCode] Serialize and Deserialize BST

Problem: Serialization is converting a data structure or object into a sequence of bits so that it can be stored in a file or memory buffer, or transmitted across a network connection link to be reconstructed later in the same or another computer environment.

Design an algorithm to serialize and deserialize a binary search tree. There is no restriction on how your serialization/deserialization algorithm should work. You need to ensure that a binary search tree can be serialized to a string, and this string can be deserialized to the original tree structure.

The encoded string should be as compact as possible.

Example:

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


Approach: We will store the preorder traversal here as inorder traversal is already known which is sorted order.


Implementation in C#:

    public string serialize(TreeNode root) 

    {

        if(root == null)

        {

            return string.Empty;

        }

        return string.Join('|', this.PreOrderSerialize(root));

    }


    public TreeNode deserialize(string data) 

    {

        if (string.IsNullOrWhiteSpace(data))

        {

            return null;

        }        

        List<string> nodeValues = data.Split("|").ToList();

        TreeNode root = new TreeNode(int.Parse(nodeValues[0]));

        this.MakeTree(nodeValues, root);        

        return root;

    }

    

    private void MakeTree(List<string> nodeValues, TreeNode root)

    {

        Stack<TreeNode> stackOfTreeVals = new Stack<TreeNode>();

        stackOfTreeVals.Push(root);

        for (int i = 1; i < nodeValues.Count; ++i)

        {

            TreeNode node = stackOfTreeVals.Peek();

            int currVal = int.Parse(nodeValues[i]);

            if (currVal < node.val)

            {

                node.left = new TreeNode(currVal);

                stackOfTreeVals.Push(node.left);

            }

            else

            {

                while(stackOfTreeVals.Count > 0 && stackOfTreeVals.Peek().val < currVal)

                {

                    node = stackOfTreeVals.Peek();

                    stackOfTreeVals.Pop();

                }

                node.right = new TreeNode(currVal);

                stackOfTreeVals.Push(node.right);

            }

        }

    }

    

    private List<string> PreOrderSerialize(TreeNode node) 

    {

        List<string> result = new List<string>();

        if (node == null)

        {

            return result;

        }

        result.Add(node.val.ToString());

        result.AddRange(this.PreOrderSerialize(node.left));

        result.AddRange(this.PreOrderSerialize(node.right));

        return result;

    }


Complexity: O(n)