分裂二叉樹的最大乘積-力扣周賽題

題目描述:

給你一棵二叉樹,它的根爲 root 。請你刪除 1 條邊,使二叉樹分裂成兩棵子樹,且它們子樹和的乘積儘可能大。

由於答案可能會很大,請你將結果對 10^9 + 7 取模後再返回

 題解:

在題目裏,將節點分爲兩組,但是這兩組就是所有元素之和,是一定的,這會讓我們想起來均值不等式

當且僅當a=b的時候取等號。所以在本題中,ab的乘積是有上限的,我們應該使得a和b儘量的接近。那麼a和b在什麼地方會很接近呢?

(虛線是省略的節點,實線是實際相連)
假設我們當前後續遍歷到X節點,Y爲X的左子樹,Z爲X的右子樹,而且(X->val)+(Y子樹數值總和)+(Z子樹數值總和)第一次大於或等於所有節點總和(記爲sum)的一半,那麼我們想找的a和b就即將找到,因爲繼續遍歷節點的話會使得a和b的差距更大,乘積就變小。所以a接下來就有三種情況:
1、a爲Y子樹數值總和,b爲sum-a
2、a爲Z子樹數值總和,b爲sum-a
3、a爲(X->val)+(Y子樹數值總和)+(Z子樹數值總和),b爲sum-a
所以只需要比較一下上面三種情況找一個ab的乘積最大的值然後返回。

代碼:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
static const int mod = 1e9 + 7;

class Solution {
public:
    //後續遍歷計算所有節點的數值之和
    long cal_sum(TreeNode* root){
        if(root==NULL) return 0;
        return root->val + cal_sum(root->left) + cal_sum(root->right);
    }
    //參數說明:quit是布爾型指針,如果quit爲真的話就說明找到最大值了,就可以直接返回了,sum爲所有節點的和
    long findVal(TreeNode* root,bool *quit,long sum)
    {
        if(root==NULL) return 0;
        //右子樹的數值之和,這裏先遍歷左子樹還是右子樹都沒有關係
        long right = findVal(root->right,quit,sum);
        //判斷是否找到最大值了,如果找到直接返回
        if(*quit) return right;
        //左子樹的數值之和
        long left = findVal(root->left,quit,sum);
        if(*quit) return left;
        //(X->val)+(Y子樹數值總和)+(Z子樹數值總和)
        int total = left+right+root->val;
        if(total>=sum/2.0)
        {
             long first = left*(sum-left);
             long second = right*(sum-right);
             long third = total*(sum-total);
             *quit = true;
            //比較三種情況中的最大值,然後置quit爲true
             return max(first,max(second,third));
        }
        else return total;
    }
    int maxProduct(TreeNode* root) {
        long sum = cal_sum(root);
        bool quit = false;
        long res = findVal(root,&quit,sum);
        return res % mod;
    }
   
};

 

發佈了67 篇原創文章 · 獲贊 40 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章