1. 程式人生 > >[LeetCode] Maximum Binary Tree 最大二叉樹

[LeetCode] Maximum Binary Tree 最大二叉樹

Given an integer array with no duplicates. A maximum tree building on this array is defined as follow:

  1. The root is the maximum number in the array.
  2. The left subtree is the maximum tree constructed from left part subarray divided by the maximum number.
  3. The right subtree is the maximum tree constructed from right part subarray divided by the maximum number.

Construct the maximum tree by the given array and output the root node of this tree.

Example 1:

Input: [3,2,1,6,0,5]
Output: return the tree root node representing the following tree:

      6
    /   \
   3     5
    \    / 
     2  0   
       \
        1

Note:

  1. The size of the given array will be in the range [1,1000].

這道題給了我們一個數組,讓我們建立一個最大二叉樹,建立規則是陣列中的最大值為根結點,然後分隔出的左右部分再分別建立最大二叉樹。那麼明眼人一看就知道這是分治法啊,果斷上遞迴啊。首先就是要先找出陣列中的最大值,由於陣列是無序的,所以沒啥好的辦法,就直接遍歷吧,找到了最大值,就建立一個結點,然後將左右兩個子陣列提取出來,分別呼叫遞迴函式並將結果連到該結點上,最後將結點返回即可,參見程式碼如下:

解法一:

class Solution {
public:
    TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
        
if (nums.empty()) return NULL; int mx = INT_MIN, mx_idx = 0; for (int i = 0; i < nums.size(); ++i) { if (mx < nums[i]) { mx = nums[i]; mx_idx = i; } } TreeNode *node = new TreeNode(mx); vector<int> leftArr = vector<int>(nums.begin(), nums.begin() + mx_idx); vector<int> rightArr = vector<int>(nums.begin() + mx_idx + 1, nums.end()); node->left = constructMaximumBinaryTree(leftArr); node->right = constructMaximumBinaryTree(rightArr); return node; } };

下面這種方法也是遞迴的解法,和上面的解法稍有不同的是不必提取子陣列,而是用兩個變數來指定子陣列的範圍,其他部分均和上面的解法相同,參見程式碼如下:

解法二:

class Solution {
public:
    TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
        if (nums.empty()) return NULL;
        return helper(nums, 0, nums.size() - 1);
    }
    TreeNode* helper(vector<int>& nums, int left, int right) {
        if (left > right) return NULL;
        int mid = left;
        for (int i = left + 1; i <= right; ++i) {
            if (nums[i] > nums[mid]) {
                mid = i;
            }
        }
        TreeNode *node = new TreeNode(nums[mid]);
        node->left = helper(nums, left, mid - 1);
        node->right = helper(nums, mid + 1, right);
        return node;
    }
};

下面這種解法是論壇上的高分解法,使用到了一個輔助陣列v來讓保持降序。我們遍歷陣列,對於每個遍歷到的數字,建立一個結點,然後進行迴圈,如果陣列v不空,且末尾結點值小於當前數字,那麼將末尾結點連到當前結點的左子結點,並且移除陣列中的末尾結點,這樣可以保證子結點都會小於父結點。迴圈結束後,如果此時陣列v仍不為空,說明結點值很大,那麼將當前結點連到陣列末尾結點的右子結點上。之後別忘了將當前結點加入陣列v中,最後返回陣列v的首結點即可,如果不太容易理解的話,就把題目中的例子帶入一步一步執行看一下吧,參見程式碼如下:

解法三:

class Solution {
public:
    TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
        vector<TreeNode*> v;
        for (int num : nums) {
            TreeNode *cur = new TreeNode(num);
            while (!v.empty() && v.back()->val < num) {
                cur->left = v.back();
                v.pop_back();
            }
            if (!v.empty()) {
                v.back()->right = cur;
            }
            v.push_back(cur);
        }
        return v.front();
    }
};

參考資料: