LeetCode 776 - Split BST


http://www.cnblogs.com/grandyang/p/8993143.html
Given a Binary Search Tree (BST) with root node root, and a target value V, split the tree into two subtrees where one subtree has nodes that are all smaller or equal to the target value, while the other subtree has all nodes that are greater than the target value.  It's not necessarily the case that the tree contains a node with value V.
Additionally, most of the structure of the original tree should remain.  Formally, for any child C with parent P in the original tree, if they are both in the same subtree after the split, then node C should still have the parent P.
You should output the root TreeNode of both subtrees after splitting, in any order.
Example 1:
Input: root = [4,2,6,1,3,5,7], V = 2
Output: [[2,1],[4,3,6,null,null,5,7]]
Explanation:
Note that root, output[0], and output[1] are TreeNode objects, not arrays.

The given tree [4,2,6,1,3,5,7] is represented by the following diagram:

          4
        /   \
      2      6
     / \    / \
    1   3  5   7

while the diagrams for the outputs are:

          4
        /   \
      3      6      and    2
            / \           /
           5   7         1
Note:
  1. The size of the BST will not exceed 50.
  2. The BST is always valid and each node's value is different.
通过观察我们首先发现,无论如何,root总是会包含在最终的返回结果中。然后就比较root的值和V的大小了:如果root的值比V大,那么root以及其右子树的结构都无需变化,只需要递归对root的左子树进行分割即可。需要注意的是,root的左子树中也有可能存在比V大的分支,所以我们需要将root的左子树中比V大的分支的树根接到root的左子树上。进一步分析可知,对root的左子树进行分割的思路和对root的分割完全一样,所以我们就可以采用递归调用进行处理了,代码十分简洁。

root的值小于等于V的情况可以对称得到处理。


这道题给了我们一棵二叉搜索树Binary Search Tree,又给了我们一个目标值V,让我们将这个BST分割成两个子树,其中一个子树所有结点的值均小于等于目标值V,另一个子树所有结点的值均大于目标值V。这道题最大的难点在于不是简单的将某条边断开就可以的,不如题目中给的那个例子,目标值为2,我们知道要断开结点2和结点4的那条边,但是以结点2为root的子树中是有大于目标值2的结点的,而这个结点3必须也从该子树中移出,并加到较大的那个子树中去的。为了具体的讲解这个过程,这里借用官方解答贴中的例子来说明问题吧。

比如对于上图,假如root结点小于V,而root.right大于V的话,那么这条边是要断开的,但是如果root.right的左子结点(结点A)是小于V的,那么其边也应该断开,如果如果root.right的左子结点的右子结点(结点B)大于V,则这条边也应该断开,所以总共有三条边需要断开,如图中蓝色虚线所示,三条粗灰边需要断开,粉细边和绿细边是需要重新连上的边。那么我们应该如何知道连上哪条边呢?不要急,听博主慢慢道来。
博主告诉你们个秘密(一般人我不告诉他),对于树的题目,二话别说,直接上递归啊,除非是有啥特别要求,否则递归都可以解。而递归的精髓就是不断的DFS进入递归函数,直到递归到叶结点,然后回溯,我们递归函数的返回值是两个子树的根结点,比如对结点A调用递归,返回的第一个是A的左子结点,第二个是结点B,这个不需要重新连接,那么当回溯到root.right的时候,我们就需要让root.right结点连接上结点B,而这个结点B是对结点A调用递归的返回值中的第二个。如果是在左边,其实是对称的,root.left连接上调用递归返回值中的第一个,这两个想通了后,代码就不难写啦
    vector<TreeNode*> splitBST(TreeNode* root, int V) {
        vector<TreeNode*> res{NULL, NULL};
        if (!root) return res;
        if (root->val <= V) {
            res = splitBST(root->right, V);
            root->right = res[0];
            res[0] = root;
        } else {
            res = splitBST(root->left, V);
            root->left = res[1];
            res[1] = root;
        }
        return res;
    }
自底向下的遍历 O(h)h为树高度O(h)h为树高度
定义一个递归函数dfs,返回一个二维数组ans,当前结点和左右子树被V分割后,ans[0]为小于等于V的部分,ans[1]为大于V的部分。

如果当前结点node大于V,则ans[1]=node,对node的左子树递归调用dfs,得到当前结点左子树的分割结果(一个二维数组nodes)。当前结点的左子树设置为nodes[1],ans[0]设置为nodes[0]

如果当前结点node小于等于V,则ans[0]=node,对node的右子树递归调用dfs,得到当前结点右子树的分割结果(一个二维数组nodes)。当前结点的右子树设置为nodes[0],ans[1]设置为nodes[1]

时间复杂度分析:每次根据当前结点的值选择递归左子树或右子树,时间复杂度为树高度O(h)
    public TreeNode[] splitBST(TreeNode root, int V) {
        if (root == null)
            return new TreeNode[]{null, null};
        if (root.val == V) {
            TreeNode right = root.right;
            root.right = null;
            return new TreeNode[]{root, right};
        }
        else if (root.val > V) {
            TreeNode[] nodes = splitBST(root.left, V);
            TreeNode left = nodes[0];
            TreeNode right = nodes[1];
            root.left = right;
            return new TreeNode[]{left,root};
        } else {
            TreeNode[] nodes = splitBST(root.right, V);
            TreeNode left = nodes[0];
            TreeNode right = nodes[1];
            root.right=left;
            return new TreeNode[]{root, right};
        }
    }

再来一种递归的思路,很简单。我们把问题进行拆分合并式求解。比如当root.val <= val时,说明root和root的左子树均小于等于val,这种结构维持,且以root为根,那么问题就转而求root右子树的分裂。因为分裂的第一颗树,是小于val的,所以需要链接到root的右子树上,详见代码。

  public TreeNode[] splitBST(TreeNode root, int V) {
    if (root == null)
      return new TreeNode[] { null, null };
    if (root.val <= V) {
      TreeNode[] res = splitBST(root.right, V);
      root.right = res[0];
      res[0] = root;
      return res;
    } else {
      TreeNode[] res = splitBST(root.left, V);
      root.left = res[1];
      res[1] = root;
      return res;
    }
  }

https://github.com/fishercoder1534/Leetcode/blob/master/src/main/java/com/fishercoder/solutions/_776.java
  public TreeNode[] splitBST(TreeNode root, int V) {
    TreeNode small = new TreeNode(0);
    TreeNode big = new TreeNode(0);
    split(root, V, small, big);
    return new TreeNode[] { small.right, big.left };
  }

  private void split(TreeNode root, int v, TreeNode small, TreeNode big) {
    if (root == null) {
      return;
    }
    if (root.val <= v) {
      small.right = root;
      TreeNode right = root.right;
      root.right = null;
      split(right, v, root, big);
    } else {
      big.left = root;
      TreeNode left = root.left;
      root.left = null;
      split(left, v, small, root);
    }

  }

X.
问题的关键在于进行切分后,树的结构不能改变。影响BST的结构在于输入顺序,所以切分前后,维持输入顺序即可。而BST的层序遍历刚好是最初的输入顺序。所以
1. 求出输入顺序。
2. 根据val划分两个子输入顺序
3. 根据子输入顺序建立BST

  public TreeNode[] splitBST(TreeNode root, int V) {
    if (root == null)
      return new TreeNode[] { null, null };
    List<Integer> nodes = new ArrayList<>();
    Queue<TreeNode> q = new ArrayDeque<>();
    q.offer(root);
    while (!q.isEmpty()) {
      TreeNode now = q.poll();
      nodes.add(now.val);
      if (now.left != null) {
        q.offer(now.left);
      }
      if (now.right != null) {
        q.offer(now.right);
      }
    }
    List<Integer> left = new ArrayList<>();
    List<Integer> right = new ArrayList<>();
    for (int val : nodes) {
      if (val <= V)
        left.add(val);
      else
        right.add(val);
    }

    TreeNode leftNode = null;
    for (int val : left)
      leftNode = build(leftNode, val);

    TreeNode rightNode = null;
    for (int val : right)
      rightNode = build(rightNode, val);

    return new TreeNode[] { leftNode, rightNode };
  }

  TreeNode build(TreeNode root, int val) {
    if (root == null)
      return new TreeNode(val);
    else {
      if (val <= root.val) {
        root.left = build(root.left, val);
      } else {
        root.right = build(root.right, val);
      }
      return root;
    }
  }




Labels

LeetCode (1432) GeeksforGeeks (1122) LeetCode - Review (1067) Review (882) Algorithm (668) to-do (609) Classic Algorithm (270) Google Interview (237) Classic Interview (222) Dynamic Programming (220) DP (186) Bit Algorithms (145) POJ (141) Math (137) Tree (132) LeetCode - Phone (129) EPI (122) Cracking Coding Interview (119) DFS (115) Difficult Algorithm (115) Lintcode (115) Different Solutions (110) Smart Algorithm (104) Binary Search (96) BFS (91) HackerRank (90) Binary Tree (86) Hard (79) Two Pointers (78) Stack (76) Company-Facebook (75) BST (72) Graph Algorithm (72) Time Complexity (69) Greedy Algorithm (68) Interval (63) Company - Google (62) Geometry Algorithm (61) Interview Corner (61) LeetCode - Extended (61) Union-Find (60) Trie (58) Advanced Data Structure (56) List (56) Priority Queue (53) Codility (52) ComProGuide (50) LeetCode Hard (50) Matrix (50) Bisection (48) Segment Tree (48) Sliding Window (48) USACO (46) Space Optimization (45) Company-Airbnb (41) Greedy (41) Mathematical Algorithm (41) Tree - Post-Order (41) ACM-ICPC (40) Algorithm Interview (40) Data Structure Design (40) Graph (40) Backtracking (39) Data Structure (39) Jobdu (39) Random (39) Codeforces (38) Knapsack (38) LeetCode - DP (38) Recursive Algorithm (38) String Algorithm (38) TopCoder (38) Sort (37) Introduction to Algorithms (36) Pre-Sort (36) Beauty of Programming (35) Must Known (34) Binary Search Tree (33) Follow Up (33) prismoskills (33) Palindrome (32) Permutation (31) Array (30) Google Code Jam (30) HDU (30) Array O(N) (29) Logic Thinking (29) Monotonic Stack (29) Puzzles (29) Code - Detail (27) Company-Zenefits (27) Microsoft 100 - July (27) Queue (27) Binary Indexed Trees (26) TreeMap (26) to-do-must (26) 1point3acres (25) GeeksQuiz (25) Merge Sort (25) Reverse Thinking (25) hihocoder (25) Company - LinkedIn (24) Hash (24) High Frequency (24) Summary (24) Divide and Conquer (23) Proof (23) Game Theory (22) Topological Sort (22) Lintcode - Review (21) Tree - Modification (21) Algorithm Game (20) CareerCup (20) Company - Twitter (20) DFS + Review (20) DP - Relation (20) Brain Teaser (19) DP - Tree (19) Left and Right Array (19) O(N) (19) Sweep Line (19) UVA (19) DP - Bit Masking (18) LeetCode - Thinking (18) KMP (17) LeetCode - TODO (17) Probabilities (17) Simulation (17) String Search (17) Codercareer (16) Company-Uber (16) Iterator (16) Number (16) O(1) Space (16) Shortest Path (16) itint5 (16) DFS+Cache (15) Dijkstra (15) Euclidean GCD (15) Heap (15) LeetCode - Hard (15) Majority (15) Number Theory (15) Rolling Hash (15) Tree Traversal (15) Brute Force (14) Bucket Sort (14) DP - Knapsack (14) DP - Probability (14) Difficult (14) Fast Power Algorithm (14) Pattern (14) Prefix Sum (14) TreeSet (14) Algorithm Videos (13) Amazon Interview (13) Basic Algorithm (13) Codechef (13) Combination (13) Computational Geometry (13) DP - Digit (13) LCA (13) LeetCode - DFS (13) Linked List (13) Long Increasing Sequence(LIS) (13) Math-Divisible (13) Reservoir Sampling (13) mitbbs (13) Algorithm - How To (12) Company - Microsoft (12) DP - Interval (12) DP - Multiple Relation (12) DP - Relation Optimization (12) LeetCode - Classic (12) Level Order Traversal (12) Prime (12) Pruning (12) Reconstruct Tree (12) Thinking (12) X Sum (12) AOJ (11) Bit Mask (11) Company-Snapchat (11) DP - Space Optimization (11) Dequeue (11) Graph DFS (11) MinMax (11) Miscs (11) Princeton (11) Quick Sort (11) Stack - Tree (11) 尺取法 (11) 挑战程序设计竞赛 (11) Coin Change (10) DFS+Backtracking (10) Facebook Hacker Cup (10) Fast Slow Pointers (10) HackerRank Easy (10) Interval Tree (10) Limited Range (10) Matrix - Traverse (10) Monotone Queue (10) SPOJ (10) Starting Point (10) States (10) Stock (10) Theory (10) Tutorialhorizon (10) Kadane - Extended (9) Mathblog (9) Max-Min Flow (9) Maze (9) Median (9) O(32N) (9) Quick Select (9) Stack Overflow (9) System Design (9) Tree - Conversion (9) Use XOR (9) Book Notes (8) Company-Amazon (8) DFS+BFS (8) DP - States (8) Expression (8) Longest Common Subsequence(LCS) (8) One Pass (8) Quadtrees (8) Traversal Once (8) Trie - Suffix (8) 穷竭搜索 (8) Algorithm Problem List (7) All Sub (7) Catalan Number (7) Cycle (7) DP - Cases (7) Facebook Interview (7) Fibonacci Numbers (7) Flood fill (7) Game Nim (7) Graph BFS (7) HackerRank Difficult (7) Hackerearth (7) Inversion (7) Kadane’s Algorithm (7) Manacher (7) Morris Traversal (7) Multiple Data Structures (7) Normalized Key (7) O(XN) (7) Radix Sort (7) Recursion (7) Sampling (7) Suffix Array (7) Tech-Queries (7) Tree - Serialization (7) Tree DP (7) Trie - Bit (7) 蓝桥杯 (7) Algorithm - Brain Teaser (6) BFS - Priority Queue (6) BFS - Unusual (6) Classic Data Structure Impl (6) DP - 2D (6) DP - Monotone Queue (6) DP - Unusual (6) DP-Space Optimization (6) Dutch Flag (6) How To (6) Interviewstreet (6) Knapsack - MultiplePack (6) Local MinMax (6) MST (6) Minimum Spanning Tree (6) Number - Reach (6) Parentheses (6) Pre-Sum (6) Probability (6) Programming Pearls (6) Rabin-Karp (6) Reverse (6) Scan from right (6) Schedule (6) Stream (6) Subset Sum (6) TSP (6) Xpost (6) n00tc0d3r (6) reddit (6) AI (5) Abbreviation (5) Anagram (5) Art Of Programming-July (5) Assumption (5) Bellman Ford (5) Big Data (5) Code - Solid (5) Code Kata (5) Codility-lessons (5) Coding (5) Company - WMware (5) Convex Hull (5) Crazyforcode (5) DFS - Multiple (5) DFS+DP (5) DP - Multi-Dimension (5) DP-Multiple Relation (5) Eulerian Cycle (5) Graph - Unusual (5) Graph Cycle (5) Hash Strategy (5) Immutability (5) Java (5) LogN (5) Manhattan Distance (5) Matrix Chain Multiplication (5) N Queens (5) Pre-Sort: Index (5) Quick Partition (5) Quora (5) Randomized Algorithms (5) Resources (5) Robot (5) SPFA(Shortest Path Faster Algorithm) (5) Shuffle (5) Sieve of Eratosthenes (5) Strongly Connected Components (5) Subarray Sum (5) Sudoku (5) Suffix Tree (5) Swap (5) Threaded (5) Tree - Creation (5) Warshall Floyd (5) Word Search (5) jiuzhang (5)

Popular Posts