You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

O(h)时间复杂度拆分二叉搜索树问题调试求助

Hey there, let's work through your tree split problem. I've examined your code and the specific test case you mentioned, and I can spot two critical issues causing the incorrect split and missing nodes.

Key Bugs in Your Current Code

  1. Lost Nodes Due to Premature Link Breaking
    In the first branch of your loop (when you take the current node and its left subtree), you immediately set prev->rc = NULL after moving to current->rc. This disconnects the right subtree of the current node (like the 30 in your test case) from both trees, leaving it orphaned. That's why your split result only has 170 and 45—30 gets lost entirely.

  2. Inefficient and Incorrect lcnt Updates

    • Using count_total_tasks to recalculate lcnt values in the else branch introduces O(n) time complexity, which violates your requirement of O(h) performance.
    • The updt function blindly decrements the lcnt of all nodes along the left path of new_root_2, which isn't correct. Only specific ancestor nodes (those whose left subtree had nodes split off) need their lcnt adjusted, not every left-path node.

Fix: Recursive Split Implementation (O(h) Time)

A recursive approach is cleaner for this problem, as it naturally traverses the tree in O(h) time and makes lcnt maintenance straightforward. Here's a corrected implementation that adheres to your requirements:

// Helper to calculate total nodes in a subtree (for validation, not required in core logic)
int get_total_nodes(struct tree *node) {
    if (!node) return 0;
    return node->lcnt + 1 + get_total_nodes(node->rc);
}

struct tree* split(struct tree *root, struct tree **new_tree, int collect) {
    if (!root) {
        *new_tree = NULL;
        return NULL;
    }

    int left_subtree_size = root->lcnt; // Total nodes in root's left subtree

    if (collect <= left_subtree_size) {
        // Split the left subtree: take 'collect' nodes from it
        struct tree *remaining_left;
        struct tree *tree1 = split(root->lc, &remaining_left, collect);
        
        // Update root's lcnt (subtract the number of nodes we took from the left)
        root->lcnt = left_subtree_size - collect;
        root->lc = remaining_left;
        
        *new_tree = root;
        return tree1;
    } else if (collect == left_subtree_size + 1) {
        // Split exactly at the root: tree1 is root + left subtree, tree2 is right subtree
        *new_tree = root->rc;
        root->rc = NULL; // Disconnect root from tree2
        return root;
    } else {
        // Split the right subtree: take (collect - left_subtree_size - 1) nodes from it
        struct tree *taken_right;
        struct tree *tree2 = split(root->rc, &taken_right, collect - (left_subtree_size + 1));
        
        // Attach the taken part of the right subtree to root
        root->rc = taken_right;
        
        *new_tree = tree2;
        return root;
    }
}

How This Fixes Your Test Case

Let's walk through your test tree (assuming lcnt is correctly set to represent the total number of nodes in the left subtree):

  • Tree structure: 170 (lcnt=2, lc=45, rc=NULL) → 45 (lcnt=0, lc=NULL, rc=30) → 30 (lcnt=0, lc=NULL, rc=NULL)
  • If you want to split into the first 2 nodes (45 and 30) and the remaining 1 node (170):
    1. Call split(170, &tree2, 2): left_subtree_size=2, so we split the left subtree (45) for collect=2.
    2. Call split(45, &remaining_left, 2): left_subtree_size=0, collect>0+1=1, so split the right subtree (30) for collect=1.
    3. Call split(30, &taken_right, 1): left_subtree_size=0, collect=0+1, so return 30 as tree1, taken_right=NULL.
    4. Back to split(45, ...): Attach taken_right=NULL to 45's rc, return 45 as tree1, remaining_left=NULL.
    5. Back to split(170, ...): Update 170's lcnt to 2-2=0, set its lc to remaining_left=NULL, return 45 (with rc=30) as tree1, tree2=170.

This gives you the expected split: tree1 has 45 and 30, tree2 has 170.

Notes for Your Iterative Code

If you prefer to stick with an iterative approach, you'll need to:

  • Avoid breaking links prematurely—only disconnect nodes once you've determined which tree they belong to.
  • Track ancestor nodes that need their lcnt adjusted, rather than traversing entire subtrees.
  • Ensure all nodes are attached to either tree1 or tree2 before exiting the loop.

内容的提问来源于stack exchange,提问作者Alexis Tevre

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 08:12:08