[LeetCode] Second Minimum Node In a Binary Tree 二叉樹中第二小的結點


 

Given a non-empty special binary tree consisting of nodes with the non-negative value, where each node in this tree has exactly two or zero sub-node. If the node has two sub-nodes, then this node's value is the smaller value among its two sub-nodes.

Given such a binary tree, you need to output the second minimum value in the set made of all the nodes' value in the whole tree.

If no such second minimum value exists, output -1 instead.

Example 1:

Input: 
    2
   / \
  2   5
     / \
    5   7

Output: 5
Explanation: The smallest value is 2, the second smallest value is 5.

 

Example 2:

Input: 
    2
   / \
  2   2

Output: -1
Explanation: The smallest value is 2, but there isn't any second smallest value.

 

這道題讓我們找二叉樹中的第二小的結點值,並且給該二叉樹做了一些限制,比如對於任意一個結點,要么其沒有子結點,要么就同時有兩個子結點,而且父結點值是子結點值中較小的那個,當然兩個子結點值可以相等。那么直接上暴力搜索唄,根據該樹的附加條件可知,根結點一定是最小的結點值first,那么我們只要找出第二小的值second即可,初始化為整型的最大值。然后對根結點調用遞歸函數,將first和second當作參數傳進去即可。在遞歸函數中,如果當前結點為空,直接返回,若當前結點孩值不等於first,說明其肯定比first要大,然后我們看其是否比second小,小的話就更新second,然后對當前結點的左右子結點分別調用遞歸函數即可,參見代碼如下:

 

解法一:

class Solution {
public:
    int findSecondMinimumValue(TreeNode* root) {
        int first = root->val, second = INT_MAX;
        helper(root, first, second);
        return (second == first || second == INT_MAX) ? -1 : second;
    }
    void helper(TreeNode* node, int& first, int& second) {
        if (!node) return;
        if (node->val != first && node->val < second) {
            second = node->val;
        }
        helper(node->left, first, second);
        helper(node->right, first, second);
    }
};

 

下面這種方法也是用遞歸來做的,不過現在遞歸函數有了返回值,在遞歸函數中,還是先判斷當前結點是否為空,為空直接返回-1。然后就是看當前結點是否等於first,不等於直接返回當前結點值。如果等於,我們對其左右子結點分別調用遞歸函數,分別得到left和right。如果left和right其中有一個為-1了,我們取其中的較大值;如果left和right都不為-1,我們取其中的較小值返回即可,參見代碼如下:

 

解法二:

class Solution {
public:
    int findSecondMinimumValue(TreeNode* root) {
        return helper(root, root->val);
    }
    int helper(TreeNode* node, int first) {
        if (!node) return -1;
        if (node->val != first) return node->val;
        int left = helper(node->left, first), right = helper(node->right, first);
        return (left == -1 || right == -1) ? max(left, right) : min(left, right);
    }
};

 

下面這種遞歸方法更加簡潔了,沒有再使用專門的遞歸函數helper,而是對當前根結點判斷其左子樹是否存在,不存在就返回-1。題目中說了是非空樹,所以根結點一定存在。然后我們比較如果左子結點值等於根結點值,我們則對其左子結點調用遞歸函數;否則left就等於其左子結點值。再比較如果右子結點值等於根結點值,則對其右子結點調用遞歸函數;否則right就等於其右子結點值。最后我們還是看如果left和right其中有一個為-1了,我們取其中的較大值;如果left和right都不為-1,我們取其中的較小值返回即可,參見代碼如下:

 

解法三:

class Solution {
public:
    int findSecondMinimumValue(TreeNode* root) {
        if (!root->left) return -1;
        int left = (root->left->val == root->val) ? findSecondMinimumValue(root->left) : root->left->val;
        int right = (root->right->val == root->val) ? findSecondMinimumValue(root->right) : root->right->val;
        return (left == -1 || right == -1) ? max(left, right) : min(left, right);
    }
};

 

整了三種遞歸的解法,來看一種迭代的解法吧,用的是層序遍歷,但還是用的解法一種的不停更新second的方法,參見代碼如下:

 

解法四:

class Solution {
public:
    int findSecondMinimumValue(TreeNode* root) {
        int first = root->val, second = INT_MAX;
        queue<TreeNode*> q{{root}};
        while (!q.empty()) {
            auto t = q.front(); q.pop();
            if (t->val != first && t->val < second) {
                second = t->val;
            }
            if (t->left) q.push(t->left);
            if (t->right) q.push(t->right);
        }
        return (second == first || second == INT_MAX) ? -1 : second;
    }
};

 

類似題目:

Kth Smallest Element in a BST

 

參考資料:

https://discuss.leetcode.com/topic/102277/java-4-lines

https://discuss.leetcode.com/topic/102027/c-dfs-recursion

https://discuss.leetcode.com/topic/102035/bfs-acc-solution-java-and-c-code

 

LeetCode All in One 題目講解匯總(持續更新中...)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM