thảo luận Leetcode mỗi ngày

Ăn ngay cái edge case node là target, còn hơi non :ah:
Python:
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def removeLeafNodes(self, root: Optional[TreeNode], target: int) -> Optional[TreeNode]:
        def dfs(node):
            if node == None:
                return False

            if dfs(node.left):
                node.left = None

            if dfs(node.right):
                node.right = None

            if node.left == None and node.right == None and node.val == target:
                return True

        dummy = TreeNode(-1, root)
        dfs(dummy)
        return dummy.left
same :shame:
 
Python:
class Solution:
    def removeLeafNodes(self, root: Optional[TreeNode], target: int) -> Optional[TreeNode]:
        def is_leaf(node: Optional[TreeNode]) -> bool:
            return not node.left and not node.right

        def remove_leaf(node: Optional[TreeNode]) -> None:
            if not node:
                return None
            
            node.left = remove_leaf(node.left)
            node.right = remove_leaf(node.right)
            
            if is_leaf(node) and node.val == target:
                return None

            return node
        
        return remove_leaf(root)
 
Medium fake này, ez quá :canny:
JavaScript:
function removeLeafNodes(root: TreeNode | null, target: number): TreeNode | null {
    if (!root) return null;
    root.left = removeLeafNodes(root.left, target);
    root.right = removeLeafNodes(root.right, target);
    if (!root.left && !root.right && root.val === target) return null;
    return root;
};
 
JavaScript:
var removeLeafNodes = function(root, target) {
    let dfs = (node) => {
        if (!node) return node;
        
        node.left = dfs(node.left);
        node.right = dfs(node.right);
        
        if (!node.left && !node.right && node.val === target) {
            return null;
        }
        
        return node;
    };

    return dfs(root);
};
 
Ăn ngay cái edge case node là target, còn hơi non :ah:
Python:
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def removeLeafNodes(self, root: Optional[TreeNode], target: int) -> Optional[TreeNode]:
        def dfs(node):
            if node == None:
                return False

            if dfs(node.left):
                node.left = None

            if dfs(node.right):
                node.right = None

            if node.left == None and node.right == None and node.val == target:
                return True

        dummy = TreeNode(-1, root)
        dfs(dummy)
        return dummy.left
em cũng bị bác ơi, submit xong ai dè sai luôn test case 4
 
C++:
class Solution {
public:
    TreeNode* removeLeafNodes(TreeNode* root, int target) {
        if (root == nullptr) {
            return nullptr;
        }

        root->left = removeLeafNodes(root->left, target);
        root->right = removeLeafNodes(root->right, target);

        if (root->val == target && root->left == nullptr && root->right == nullptr) {
            root = nullptr;
        }

        return root;
    }
};
 
Java:
class Solution {
    public TreeNode removeLeafNodes(TreeNode root, int target) {
        return dfs(root, target);
    }

    private TreeNode dfs(TreeNode root, int target) {
        if (root == null) return null;
    
        root.left = dfs(root.left, target);
        root.right = dfs(root.right, target);

        if (root.left == null && root.right == null && root.val == target) return null;

        return root;
    }
}
 
Ăn ngay cái edge case node là target, còn hơi non :ah:
Python:
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def removeLeafNodes(self, root: Optional[TreeNode], target: int) -> Optional[TreeNode]:
        def dfs(node):
            if node == None:
                return False

            if dfs(node.left):
                node.left = None

            if dfs(node.right):
                node.right = None

            if node.left == None and node.right == None and node.val == target:
                return True

        dummy = TreeNode(-1, root)
        dfs(dummy)
        return dummy.left
Công nhận hơi non thật, :rolleyes:

K cần dùng dummy node nhé.

Python:
class Solution:
    def removeLeafNodes(self, root: Optional[TreeNode], target: int) -> Optional[TreeNode]:
        if not root:
            return root
        root.left = self.removeLeafNodes(root.left, target)
        root.right = self.removeLeafNodes(root.right, target)
        if not root.left and not root.right and root.val == target:
            return None
        return root
 
Công nhận hơi non thật, :rolleyes:

K cần dùng dummy node nhé.

Python:
class Solution:
    def removeLeafNodes(self, root: Optional[TreeNode], target: int) -> Optional[TreeNode]:
        if not root:
            return root
        root.left = self.removeLeafNodes(root.left, target)
        root.right = self.removeLeafNodes(root.right, target)
        if not root.left and not root.right and root.val == target:
            return None
        return root
DNA giới hạn rồi :look_down:
 
Code 1 nạm xong ra thấy tụi nó đệ quy có mấy dòng :cold:
C#:
public class Solution
{
    public TreeNode RemoveLeafNodes(TreeNode root, int target)
    {
        Stack<(TreeNode, TreeNode)> st = new();
        TreeNode dummy = new(0, root, null);

        BFS(root, dummy, st);
        while (st.Count > 0)
        {
            var (node, parent) = st.Pop();
            if (node.left == null && node.right == null && node.val == target)
            {
                node.val = int.MaxValue;
                if (parent.left?.val == int.MaxValue)
                {
                    parent.left = null;
                }
                if (parent.right?.val == int.MaxValue)
                {
                    parent.right = null;
                }
            }
        }

        return dummy.left;
    }

    private void BFS(TreeNode root, TreeNode dummy, Stack<(TreeNode, TreeNode)> st)
    {
        Queue<TreeNode> q = new();
        q.Enqueue(root);
        st.Push((root, dummy));
        while (q.Count > 0)
        {
            TreeNode node = q.Dequeue();
            if (node.left != null)
            {
                q.Enqueue(node.left);
                st.Push((node.left, node));
            }
            if (node.right != null)
            {
                q.Enqueue(node.right);
                st.Push((node.right, node));
            }
        }
    }
}
 
C#:
public class Solution {
    public TreeNode PostOrder(TreeNode root, int target)
    {
        if(root.left != null)
            root.left = PostOrder(root.left, target);
        if(root.right != null)
            root.right = PostOrder(root.right, target);
        if(root.val == target && root.left == null && root.right == null)
            return null;
        else return root;
    }
    public TreeNode RemoveLeafNodes(TreeNode root, int target) {
        root = PostOrder(root, target);
        return root;
    }
}
 
Java:
class Solution {
    public TreeNode removeLeafNodes(TreeNode root, int target) {
        if(root==null) return null;
    
        TreeNode leftNode = removeLeafNodes(root.left,target);
        TreeNode rightNode = removeLeafNodes(root.right, target);
        if(leftNode==null){
            root.left=null;
        }
        if(rightNode==null){
            root.right=null;
        }
        if(leftNode==null&& rightNode==null && root.val==target){
            root=null;
        }
        return root;
    }

}
 
Ruby:
# Definition for a binary tree node.
# class TreeNode
#     attr_accessor :val, :left, :right
#     def initialize(val = 0, left = nil, right = nil)
#         @val = val
#         @left = left
#         @right = right
#     end
# end
# @param {TreeNode} root
# @param {Integer} target
# @return {TreeNode}
def remove_leaf_nodes(node, target)
    node.left = remove_leaf_nodes(node.left, target) if node.left
    node.right = remove_leaf_nodes(node.right, target) if node.right

    return nil if node.left.nil? && node.right.nil? && node.val == target

    node
end
 
Dính asan do delete root :mad:.
Sao ko cho vào luôn requirement nhỉ?

C++:
class Solution {
public:
    TreeNode* removeLeafNodes(TreeNode* node, int target) {
        if (node->left) {
            node->left = removeLeafNodes(node->left, target);
        }

        if (node->right) {
            node->right = removeLeafNodes(node->right, target);
        }

        if (node->left == NULL && node->right == NULL && node->val == target) {
            node->~TreeNode();
            return NULL;
        }

        return node;
    }
};
 
C++:
class Solution {
public:
  TreeNode *removeLeafNodes(TreeNode *root, int target) {
    if (root == NULL)
      return NULL;
    root->left = removeLeafNodes(root->left, target);
    root->right = removeLeafNodes(root->right, target);
    if (root->val == target && root->left == root->right)
      return NULL;
    return root;
  }
};
 
C++:
class Solution {
public:
  TreeNode *removeLeafNodes(TreeNode *root, int target) {
    if (root == NULL)
      return NULL;
    root->left = removeLeafNodes(root->left, target);
    root->right = removeLeafNodes(root->right, target);
    if (root->val == target && root->left == root->right)
      return NULL;
    return root;
  }
};
10 năm rồi chưa code C++, viết vầy không rõ có bị leak không 🤔
 
Elegant Recursion
Python:
class Solution:
    def removeLeafNodes(self, root: Optional[TreeNode], target: int) -> Optional[TreeNode]:
        def postOrder(root):
            if not root:
                return None
            root.left = postOrder(root.left)
            root.right = postOrder(root.right)
            if not root.left and not root.right and root.val == target:
                return None
            return root

        return postOrder(root)

Overcomplicated Iteration
- Intuition:
  • Quan sát thấy cần duyệt post-order trên tree, vì việc quyết định xoá node root dựa vào kết quả của quá trình xoá trên nhánh root.left và root.right => dùng stack lưu nodes để simulate quá trình duyệt post-order.
  • Ở từng iteration, xem xét top node của stack, có 2 trạng thái:
  1. topNode.left và topNode.right đã được duyệt qua trước đó: pop topNode ra khỏi stack, xem xét việc remove topNode dựa vào kết quả của topNode.left và topNode.right.
  2. topNode.left và topNode.right chưa được duyệt qua: push topNode.left và topNode.right vào stack.
  • Làm sao để biết được topNode.left và topNode.right đã được duyệt qua hay chưa? Solution của mình là dùng một hashmap để lưu result của từng node trên tree, qua đó có thể tham chiếu tới trạng thái node con của topNode.

Python:
class Solution:
    def removeLeafNodes(self, root: Optional[TreeNode], target: int) -> Optional[TreeNode]:
        def removeIfNeeded(node):
            if not node.left and not node.right and node.val == target:
                return None
            return node

        def allDescendantsVisited(node):
            return ((not node.left or node.left in resultMap)
                    and (not node.right or node.right in resultMap))

        st = [root]
        resultMap = {}
        while st:
            curNode = st[-1]
            if allDescendantsVisited(curNode):
                st.pop()
                curNode.left = resultMap.pop(curNode.left, None)
                curNode.right = resultMap.pop(curNode.right, None)
                resultMap[curNode] = removeIfNeeded(curNode)
                continue
        
            if curNode.right:
                st.append(curNode.right)
            if curNode.left:
                st.append(curNode.left)

        return resultMap[root]
 
Last edited:
Back
Top