[June training camp] day29 divide and conquer

It is actually very simple to think clearly about recursion;

654. Maximum Binary Tree

Title description:

Given a unique array of integers nums . A maximal binary tree can be constructed recursively from nums using the following algorithm:

Creates a root node whose value is the largest value in nums.
Recursively builds the left subtree on the subarray prefix to the left of the maximum value.
Recursively builds the right subtree on the subarray suffix to the right of the maximum value.
Returns the largest binary tree constructed by nums.

Ideas:

The construction of the binary tree is a recursive process, determine the root node, construct the left subtree, and construct the right subtree;

In the left subtree, determine the root node, construct the left subtree of the left subtree, and construct the right subtree of the left subtree;

In the right subtree, determine the root node, construct the left subtree of the right subtree, and construct the right subtree of the right subtree;

. . . Behind is the process of nesting dolls.

My understanding: Recursion is the process of nesting dolls, a process of nesting one or several in a regular manner.

This question is to use the maximum value as the root node every time, the left side of the maximum value is used as the composition of the left subtree, and the right side of the maximum value is used as the composition of the right subtree, and then the left subtree and the right subtree are recursively constructed.

First of all, it is necessary to determine the maximum value as the value of the root node, and then determine the interval of the left subtree and the interval of the right subtree, so as to facilitate the recursive construction of the left subtree and the right subtree.

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
    //构建二叉树
    TreeNode* dfs(vector<int>& nums, int start, int end)
    {
        if (start > end) {
            return NULL;
        }
        int maxid = start;
        for (int i = start; i <= end; ++i) {
            if (nums[i] > nums[maxid]) {
                maxid = i;
            }
        }
        TreeNode *root = new TreeNode(nums[maxid]);
        root->left = dfs(nums, start, maxid-1);
        root->right = dfs(nums, maxid+1, end);
        return root;
    }

public:
    TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
        return dfs(nums, 0, nums.size()-1);
    }
};

889. Construct Binary Tree Based on Preorder and Postorder Traversal

Title description:

Given two integer arrays, preorder and postorder, where preorder is a preorder traversal of a binary tree with no duplicate values ​​and postorder is a postorder traversal of the same tree, reconstruct and return the binary tree.

If multiple answers exist, you can return any of them.

Ideas:

The first node of the pre-order traversal must be the root node, and the last node of the subsequent traversal must be the root node; the
pre-order traversal starts from the second node, and the left half must be the left subtree, and the right half is the right subtree. Subsequent traversals also meet the same conditions, so there must be a dividing point, find a way to find this dividing point, and then you can distinguish the left and right subtrees.
Since the value of the node is less than or equal to 30, all the nodes can be combined and represented by bit operation, and some nodes can be represented by a mask, and then divide and conquer;

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
    TreeNode* dfs(vector<int>& preorder, vector<int>& postorder, int prel, int prer, int postl, int postr) {
        if (prel > prer) {
            return NULL;
        }        
        //  确定根结点
        TreeNode* root = new TreeNode(preorder[prel]);//根结点  postorder  左 右 根

        if (prel == prer) {
            return root;
        }

        int premask = 0, postmask = 0;
        int i = 0;
        while(1) {
            premask |= (1 << preorder[prel+i+1]);
            postmask |= (1 << postorder[postl+i]);
            
            if (postmask == premask) { //前面的点都是左子树上的点
                root->left = dfs(preorder, postorder, prel + 1, prel+i+1, postl, postl+i);
                root->right = dfs(preorder, postorder, prel+i+1+1, prer, postl+i+1, postr-1);
                return root;
            }
            i++;
        }
        return NULL;
                
    }

public:
    TreeNode* constructFromPrePost(vector<int>& preorder, vector<int>& postorder) {
        return dfs(preorder, postorder, 0, preorder.size()-1, 0, postorder.size()-1);
    }
};

1569. Number of Solutions to Reorder Subarrays to Get the Same Binary Search Tree

Title description:

You are given an array nums representing a permutation from 1 to n. We sequentially insert elements into an initially empty binary search tree (BST) in the order in which they appear in nums. Please count the number of solutions that satisfy the following conditions after reordering nums: the binary search tree obtained after rearranging is the same as the binary search tree obtained by the original numerical order of nums.

Say, given your nums = [2,1,3], we get a tree with 2 as the root, 1 as the left child, and 3 as the right child. The array [2,3,1] also gets the same BST, but [3,2,1] gets a different BST.

Please return the number of solutions that get the same binary search tree as the original array nums after rearranging nums.

Since the answer can be very large, take the remainder of the result by 10^9 + 7.

Ideas:

1. First, construct this binary search tree, and the construction process can be directly skipped and inserted;
2. Assuming a node x, the number of solutions obtained by the following method is f(x), then its The number of solutions in the left subtree is f(xl), the number of solutions in the right subtree is f(xr), and the number of nodes in the left subtree is cxl, and the number of nodes in the right subtree is cxr, then it is a permutation and combination problem;
3 , Obtain f(x)=x[cxl+cxr][cxl]*f(xl)*f(xr), c[i][j] is the number of combinations, indicating the number of options for selecting j from the i-th one. The idea used here is the interpolation method we learned in high school;
4. Then use the divide and conquer method to simulate this process.

class Solution {
    #define mod 1000000007
    #define maxn 1010
    long long c[maxn][maxn];
    //二叉搜索树的插入
    TreeNode* insert(TreeNode *root, int val) {
        if (root == NULL) {
            return new TreeNode(val);
        }
        if (val < root->val) {
            root->left = insert(root->left, val);
        } else  if (val > root->val){
            root->right = insert(root->right, val);
        }
        return root;
    }
    int count(TreeNode *root) {
        if (root == NULL) return 0;
        return count(root->left) + count(root->right) + 1;
    } 

    //对数进行遍历,得到的方案数用ans表示
    long long  dfs(TreeNode *root) {
        if (root == NULL) {
            return 1;
        }
        long long ans = dfs(root->left) * dfs(root->right) % mod;
        //统计左右子树的个数
        int lc = count(root->left);
        int rc = count(root->right);
        ans *= c[lc+rc][lc];
        ans %= mod;
        return ans;

    }
    
public:
    int numOfWays(vector<int>& nums) {
        int i, j;
        int n = nums.size();
        //构造搜索二叉树
        TreeNode *root = NULL;
        for (int i = 0; i < n; ++i) {
            root = insert(root, nums[i]);
        }

        for (i = 0; i <= n; ++i) {
            for (j = 0; j <= i; ++j) {
                if (j == 0 || i == j) {
                    c[i][j] = 1;
                } else {
                    c[i][j] = (c[i-1][j] + c[i-1][j-1]) % mod;
                }
            }
        }
        return dfs(root)-1;

    }
};

Guess you like

Origin blog.csdn.net/ilovejujube/article/details/125518432