Some conclusions about binary search tree

Frankly, I have always felt that the tree structure is particularly complex, mainly I do not really know recursive process, so always forget (just now, I forgot how to become an ordered array BST), mainly so I do not understand it ...... summarize for next query.

BST binary search tree is a very common structure, and there are some particularly good properties:

  1. Values ​​of all the nodes of the node N is less than the left subtree of the node N is equal to
  2. Values ​​of all the nodes of the node N is greater than the right subtree of the node N is equal to
  3. Left subtree and right subtree are also BST

Because of such characteristics, so BST has a very important feature: preorder is in fact the result of an ordered array. This property can be used to solve some problems.

In addition, for the convenience of explanation, the TreeNode structure is defined hereinafter as follows:

struct TreeNode
{
    int val;
    TreeNode *left;
    TreeNode *right;
    TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};

The first is to convert into an ordered array of BST, this can be achieved using the dichotomy:

TreeNode *getBST(vector<int> &nums, int b, int e)
{
    if (b == e)
    {
        return new TreeNode(nums[b]);
    }
    if (b > e)
    {
        return nullptr;
    }
    int mid = (b + e + 1) / 2;
    TreeNode *root = new TreeNode(nums[mid]);
    root->left = getBST(nums, b, mid - 1);
    root->right = getBST(nums, mid + 1, e);
    return root;
}

If a large amount of data, the intermediate seek mid similar process can be changed b + ( e - b ) / 2to avoid overflow subtraction by addition.

Then compare the use of a special kind: the number of binary search tree all the requirements and minimum absolute difference. Looks have nothing, in fact, is a kind of all depends on the context of the current value, because preorder binary search tree is ordered in. If in the context of an array, such as the number of the congregation seeking an ordered array, the first reaction is definitely to get a counter each time it encounters a different number on empty, and then find the maximum number, probably like this ( If the mode is more than one return):

vector<int> findModeInArray(vector<int> &arr)
{
    vector<int> mode;
    int max_count = 0;
    int cur_count = 1;
    int length = arr.size();
    for (int i = 1; i < length; ++i)
    {
        cur_count = arr[i] == arr[i - 1] ? cur_count + 1 : 1;

        if (cur_count == max_count)
        {
            mode.push_back(arr[i]);
        }
        else if (cur_count > max_count)
        {
            mode.clear();
            mode.push_back(arr[i]);
            max_count = cur_count;
        }
    }
    return mode;
}

If placed in the context of the next BST, it is the same, is more of a "translation" process. Further, since the recursion, we need to save time context parameter of the function. If you use global variables, global variables are unexpected situation changes may occur. Solutions from junstat @LeetCode:

void inOrder(TreeNode* root, TreeNode*& pre, int& curTimes, 
             int& maxTimes, vector<int>& res){
    if (!root) return;
    inOrder(root->left, pre, curTimes, maxTimes, res);
    if (pre)
        curTimes = (root->val == pre->val) ? curTimes + 1 : 1;
    if (curTimes == maxTimes)
        res.push_back(root->val);
    else if (curTimes > maxTimes){
        res.clear();
        res.push_back(root->val);
        maxTimes = curTimes;
    }
    pre = root;
    inOrder(root->right, pre, curTimes, maxTimes, res);
}
vector<int> findMode(TreeNode* root) {
    vector<int> res;
    if (!root) return res;
    TreeNode* pre = NULL;
    int curTimes = 1, maxTimes = 0;
    inOrder(root, pre, curTimes, maxTimes, res);
    return res;
}

It can be seen, almost exactly the same, the only difference is that the context is used for the array to traverse the loop, used in the context of BST is the recursive traversal sequence, and then use each iteration the data on the parameters in (meaning a little closure).

BST is then the minimum absolute difference. Because it is ordered, it will inevitably produce the smallest absolute difference between two adjacent elements. Context on the array, is reduced after each use a previous, then find the difference between the minimum value, nothing to say; in the context of the BST, be like this:

void inOrderTraverse(TreeNode *root, TreeNode *&pre, int &min_diff)
{
    if (root)
    {
        inOrderTraverse(root->left, pre, min_diff);
        if (pre)
        {
            min_diff = min(root->val - pre->val, min_diff);
        }
        pre = root;
        inOrderTraverse(root->right, pre, min_diff);
    }
}

int getMinimumDifference(TreeNode *root)
{
    TreeNode *pre = nullptr;
    int min_diff = INT_MAX; // #include <climits>
    inOrderTraverse(root, pre, min_diff);
    return min_diff;
}

And later saw a tree to accumulate BST become the subject:

Given a binary search tree (Binary Search Tree), it is converted into accumulated trees (Greater Tree), such that the value of each node is the original value of the node plus all its node value is greater than the sum.

This little bit special, I began to think that the preorder, and then save each Node HashMap corresponding accumulated value, and then iterate again modify the value of the original tree (I seem to particularly like HashMap?):

unordered_map<int, int> sum_map;

void traverse(TreeNode *root)
{
    if (root)
    {
        traverse(root->left);

        for (auto &p : sum_map)
        {
            p.second += root->val;
        }
        sum_map[root->val] = root->val;

        traverse(root->right);
    }
}

void convert(TreeNode *root)
{
    if (root)
    {
        convert(root->left);
        root->val = sum_map[root->val];
        convert(root->right);
    }
}

TreeNode *convertBST(TreeNode *root)
{
    traverse(root);
    convert(root);
    return root;
}

The results came out 220ms, people are stupid. Then watched solution to a problem, but also found preorder backwards with, the prevailing mood is really difficult to put into words:

int sum = 0;

TreeNode *convertBST(TreeNode *root)
{
    if (root)
    {
        convertBST(root->right);

        sum += root->val;
        root->val = sum;

        convertBST(root->left);
    }
    return root;
}

But think of it, if it is in the context of an array, is probably such a practice. So, summarized down, BST probably is the subject of such a practice, saying that it is also very simple:

  1. Consider the practice in the context of an array
  2. Recursive preorder

Finally, add that, CSDN the editor actually does not recognize md c ++, can only recognize cpp?

Published 92 original articles · won praise 108 · views 30000 +

Guess you like

Origin blog.csdn.net/HermitSun/article/details/104101536