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

  • Người tạo chủ đề Người tạo chủ đề _Gia_Cat_Luong_
  • Ngày bắt đầu Ngày bắt đầu
Trạng thái
Không mở để trả lời thêm.
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]
 
Sửa lần cuối:
JavaScript:
var removeLeafNodes = function(root, target) {
    function recursion(node) {
        if (!node) return false;

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

        return !node.left && !node.right && node.val === target;
    }

    if (recursion(root)) {
        return null;
    }

    return root;
};
 
Mã:
class Solution {
public:
    TreeNode* removeLeafNodes(TreeNode*& root, int target) {
        if (!root)
            return root;
        removeLeafNodes(root->left, target);
        removeLeafNodes(root->right, target);
        if (!root->left && !root->right && root->val == target) {
            root = nullptr;
        }
        return root;
    }
};
 
Sửa lần cuối:
C-like:
/**
 * Example:
 * var ti = TreeNode(5)
 * var v = ti.`val`
 * Definition for a binary tree node.
 * class TreeNode(var `val`: Int) {
 *     var left: TreeNode? = null
 *     var right: TreeNode? = null
 * }
 */
class Solution {
    fun removeLeafNodes(root: TreeNode?, target: Int): TreeNode? {
         if (root == null) {
            return null
        }
        root.left = removeLeafNodes(root.left, target)
        root.right = removeLeafNodes(root.right, target)
        return if (root.left == null && root.right == null && root.`val` == target) {
            null
        } else {
            root
        }
    }
}
 
C-like:
/**
 * Example:
 * var ti = TreeNode(5)
 * var v = ti.`val`
 * Definition for a binary tree node.
 * class TreeNode(var `val`: Int) {
 *     var left: TreeNode? = null
 *     var right: TreeNode? = null
 * }
 */
class Solution {
    fun removeLeafNodes(root: TreeNode?, target: Int): TreeNode? {
         if (root == null) {
            return null
        }
        root.left = removeLeafNodes(root.left, target)
        root.right = removeLeafNodes(root.right, target)
        return if (root.left == null && root.right == null && root.`val` == target) {
            null
        } else {
            root
        }
    }
}
<3
 
Nhìn AC xong hí hửng, đọc đề xong ko có ý tưởng gì luôn đệt mẹ :ah:
Bài này giải bằng backtracking thì đơn giản cơ mà constrain này thì ko backtracking được rồi
 
Nhìn AC xong hí hửng, đọc đề xong ko có ý tưởng gì luôn đệt mẹ :ah:
Bài này giải bằng backtracking thì đơn giản cơ mà constrain này thì ko backtracking được rồi
Mỗi node 1 coin nên chỉ cần so sánh số coin nó hold với số nodes của mỗi sub tree là ra được số lượng move đến root của sub tree đó. Làm tương tự, đệ quy với các subtree nhỏ hơn. => Bài này chỉ cần viết đệ quy bt thôi

Python:
class Solution:
    def distributeCoins(self, root: Optional[TreeNode]) -> int:
        def dfs(node):
            if not node:
                return 0,0,0
            l_num_nodes, l_num_coins, l_num_move = dfs(node.left)
            r_num_nodes, r_num_coins, r_num_move = dfs(node.right)
            num_nodes = l_num_nodes + r_num_nodes + 1
            num_coins = l_num_coins + r_num_coins + node.val
            num_move = abs(l_num_nodes - l_num_coins) + abs(r_num_nodes - r_num_coins) + l_num_move + r_num_move
            return num_nodes, num_coins, num_move
        return dfs(root)[2]
 
Ae cho mình hỏi sao code này với code này lại cho kết quả khác nhau nhỉ, chỗ mình bôi đậm cho kết quả khác nhau, cái 1 ra kết quả đúng cái 2 lại ra kết quả sai :ah:
Input
nums1 =
[72,97,8,32,15]
nums2 =
[63,97,57,60,83]
Ngồi cả tiếng ko biết sao nó sai cay thật :ah: cái chỗ khác nhau là chỗ current ...ấy
À thường phép toán sẽ được ưu tiên phép bitwise, phải để ý mới được ko bug sml
Python:
class Solution:
    def minimumXORSum(self, nums1: List[int], nums2: List[int]) -> int:
        n = len(nums1)

        @lru_cache(None)
        def dp(i, mask):
            if i == n:
                return 0
         
            ans = inf
            for j in range(n):
                if (mask >> j) & 1 == 0:
                    current = nums1[i]^nums2[j]
                    ans = min(ans, current + dp(i + 1, mask|(1 << j)))

            return ans

        return dp(0, 0)
Python:
class Solution:
    def minimumXORSum(self, nums1: List[int], nums2: List[int]) -> int:
        n = len(nums1)

        @lru_cache(None)
        def dp(i, mask):
            if i == n:
                return 0
         
            ans = inf
            for j in range(n):
                if (mask >> j) & 1 == 0:
                    ans = min(ans, nums1[i]^nums2[j] + dp(i + 1, mask|(1 << j)))

            return ans

        return dp(0, 0)
 
Sửa lần cuối:
Mỗi node 1 coin nên chỉ cần so sánh số coin nó hold với số nodes của mỗi sub tree là ra được số lượng move đến root của sub tree đó. Làm tương tự, đệ quy với các subtree nhỏ hơn. => Bài này chỉ cần viết đệ quy bt thôi

Python:
class Solution:
    def distributeCoins(self, root: Optional[TreeNode]) -> int:
        def dfs(node):
            if not node:
                return 0,0,0
            l_num_nodes, l_num_coins, l_num_move = dfs(node.left)
            r_num_nodes, r_num_coins, r_num_move = dfs(node.right)
            num_nodes = l_num_nodes + r_num_nodes + 1
            num_coins = l_num_coins + r_num_coins + node.val
            num_move = abs(l_num_nodes - l_num_coins) + abs(r_num_nodes - r_num_coins) + l_num_move + r_num_move
            return num_nodes, num_coins, num_move
        return dfs(root)[2]
Hay quá fence, mình nghĩ ko ra xem solution luôn rồi :ah:
 
Java:
class Solution {
    public int[] divideAndConquer(TreeNode root) {
        if (root == null)
            return new int[]{0, 1};
        int[] lt = divideAndConquer(root.left);
        int[] rt = divideAndConquer(root.right);
        int[] res = new int[2];
        int leftVal = root.left == null ? 1 : root.left.val;
        int rightVal = root.right == null ? 1 : root.right.val;
        res[0] = lt[0] + rt[0] + Math.abs(lt[1] - leftVal) + Math.abs(rt[1] - rightVal);
        res[1] = lt[1] + rt[1] - leftVal - rightVal + 1;
        return res;
    }

    public int distributeCoins(TreeNode root) {
        int[] res = divideAndConquer(root);
        return res[0];
    }
}

Bài này thấy tiệm cận hard rồi, mà accept rate cao quá
 
Trạng thái
Không mở để trả lời thêm.

Thống kê chủ đề

Ngày tạo
_Gia_Cat_Luong_,
Người trả lời cuối
Vipluckystar,
Trả lời
17.755
Lượt xem
1.213.701
Quay lại
Lên đầu trang