📌  相关文章
📜  给定二叉树的第二个唯一最小值,其每个节点都是其子节点中的最小值

📅  最后修改于: 2022-05-13 01:56:10.225000             🧑  作者: Mango

给定二叉树的第二个唯一最小值,其每个节点都是其子节点中的最小值

给定一个完整的二叉树,其中每个节点的值与其子节点之间的最小值相同,任务是找到树的第二个最小唯一值。

例子:

Naive Approach:解决问题的基本方法是基于以下思想:

请按照以下步骤更清楚地了解该方法:

  • 遍历树并将所有值存储在一个数组中。
  • 对数组进行排序。
  • 遍历数组并找到不等于数组最小元素的第一个数组元素(即索引0 处的元素)。如果不存在这样的元素,则返回 -1。

下面是上述方法的实现。

C++
// C++ code to implement the above approach
 
#include 
using namespace std;
 
// Structure of a tree node
struct Node {
    int data;
    struct Node* left;
    struct Node* right;
    Node(int val)
    {
        data = val;
        left = NULL;
        right = NULL;
    }
};
 
// Initilize a vector
vector ans;
 
// Traversing the tree by using inorder
// traversal
void inorderTraversal(Node* root)
{
    if (root != NULL) {
        inorderTraversal(root->left);
        ans.push_back(root->data);
        inorderTraversal(root->right);
    }
}
 
// Function to find the second minimum element
int findSecondMinimumValue(Node* root)
{
    inorderTraversal(root);
 
    // Sorting the array element
    sort(ans.begin(), ans.end());
 
    // Traversing and array and checking
    // the second minimum element
    for (int i = 0; i < ans.size() - 1; i++)
        if (ans[i] != ans[i + 1])
            return ans[i + 1];
    return -1;
}
 
// Driver code
int main()
{
    // Creating the tree
    // 2
    //        / \
    // 2   5
    //          / \
    // 5   7
    struct Node* root = new Node(2);
    root->left = new Node(2);
    root->right = new Node(5);
    root->right->left = new Node(5);
    root->right->right = new Node(7);
 
    // Function call
    int SecondMinimumValue
        = findSecondMinimumValue(root);
    cout << SecondMinimumValue << endl;
    return 0;
}


Java
// JAVA code to implement the above approach
import java.util.*;
 
class GFG
{
 
  // Structure of a tree node
  public static class Node {
    int data;
    Node left;
    Node right;
    Node(int val) { this.data = val; }
  }
 
  // Initilize a vector
  public static ArrayList ans
    = new ArrayList();
 
  // Traversing the tree by using inorder
  // traversal
  public static void inorderTraversal(Node root)
  {
    if (root != null) {
      inorderTraversal(root.left);
      ans.add(root.data);
      inorderTraversal(root.right);
    }
  }
 
  // Function to find the second minimum element
  public static int findSecondMinimumValue(Node root)
  {
    inorderTraversal(root);
 
    // Sorting the array element
    Collections.sort(ans);
 
    // Traversing and array and checking
    // the second minimum element
    for (int i = 0; i < ans.size() - 1; i++)
      if (ans.get(i) != ans.get(i + 1))
        return ans.get(i + 1);
    return -1;
  }
 
  // Driver code
  public static void main(String[] args)
  {
    // Creating the tree
    // 2
    //        / \
    // 2   5
    //          / \
    // 5   7
    Node root = new Node(2);
    root.left = new Node(2);
    root.right = new Node(5);
    root.right.left = new Node(5);
    root.right.right = new Node(7);
 
    // Function call
    int SecondMinimumValue
      = findSecondMinimumValue(root);
    System.out.println(SecondMinimumValue);
  }
}
 
// This code is contributed by Taranpreet


C++
// C++ program for above approach
 
#include 
using namespace std;
 
// Structure of a tree node
struct Node {
    int data;
    struct Node* left;
    struct Node* right;
    Node(int val)
    {
        data = val;
        left = NULL;
        right = NULL;
    }
};
 
// Function to find the minimum value
int findSecondMinimumValue(Node* root)
{
    // When the root is null
    if (!root)
        return -1;
 
    // Base Condition
    // When we reach the Leaf node then
    // in that case we have to return -1
    // as per the algorithm stated in
    // the above statement
    if (!root->left && !root->right)
        return -1;
 
    // Storing the Node value of the left
    // child of the Node
    auto left = root->left->data;
 
    // Storing the Node value of the right
    // child of the Node
    auto right = root->right->data;
 
    // Call the function recursively to the
    // left sub-part of the tree if the value
    // of the node value matches with its left
    // child node value
    if (root->data == root->left->data)
        left
            = findSecondMinimumValue(root->left);
 
    // Call the function recursively to the
    // right sub-part of the tree if the
    // value of the node value matches with
    // its right child node value
    if (root->data == root->right->data)
        right
            = findSecondMinimumValue(root->right);
 
    // In case if both the left and right
    // child value is not equal to -1 then
    // in that case return the minimum of
    // them to the its parent
    if (left != -1 && right != -1)
        return min(left, right);
 
    // In case if the left child's value is
    // not equal to -1 BUT its right child's
    // value is equal to -1 then in that case
    // send the left child value to its
    // parent node.
    else if (left != -1)
        return left;
 
    // In case if the right child's value is
    // not equal to -1 BUT its left child's
    // value is equal to -1 then in that case
    // send the right child value to its
    // parent node.
    else
        return right;
}
 
// Driver code
int main()
{
    // Creating the root node
    /*         2
              / \
             2   5
                / \
               5   7 */
    struct Node* root = new Node(2);
    root->left = new Node(2);
    root->right = new Node(5);
    root->right->left = new Node(5);
    root->right->right = new Node(7);
 
    int SecondMinimumValue
        = findSecondMinimumValue(root);
    cout << SecondMinimumValue << endl;
    return 0;
}


输出
5

时间复杂度: O(N * logN)
辅助空间: O(N)

有效的方法:通过使用以下观察可以有效地解决问题:

上述观察可以使用递归来实现。按照下面提到的方法来实现上述观察的想法:

  • 使用递归函数遍历树并实现观察。
  • 在任何节点的每次递归中:
    • 找出它的哪个孩子与根具有相同的值,并为该孩子调用下一个递归。
    • 如果当前节点的值与根相同并且没有任何子节点,或者两个子节点的值相同,则将其值替换为-1
    • 如果当前节点有子节点,则在从递归函数返回时将其替换为其最小的子节点。 (这将用第二个最小值替换该值,因为最小值被替换为-1并且 -1 不被考虑用于检查最小值)。
  • 这样,当遍历完成时,树根保存了树的当前最小值,这实际上是原始树的第二个最小值。
  • 返回根的值

以下是上述方法的代码:

C++

// C++ program for above approach
 
#include 
using namespace std;
 
// Structure of a tree node
struct Node {
    int data;
    struct Node* left;
    struct Node* right;
    Node(int val)
    {
        data = val;
        left = NULL;
        right = NULL;
    }
};
 
// Function to find the minimum value
int findSecondMinimumValue(Node* root)
{
    // When the root is null
    if (!root)
        return -1;
 
    // Base Condition
    // When we reach the Leaf node then
    // in that case we have to return -1
    // as per the algorithm stated in
    // the above statement
    if (!root->left && !root->right)
        return -1;
 
    // Storing the Node value of the left
    // child of the Node
    auto left = root->left->data;
 
    // Storing the Node value of the right
    // child of the Node
    auto right = root->right->data;
 
    // Call the function recursively to the
    // left sub-part of the tree if the value
    // of the node value matches with its left
    // child node value
    if (root->data == root->left->data)
        left
            = findSecondMinimumValue(root->left);
 
    // Call the function recursively to the
    // right sub-part of the tree if the
    // value of the node value matches with
    // its right child node value
    if (root->data == root->right->data)
        right
            = findSecondMinimumValue(root->right);
 
    // In case if both the left and right
    // child value is not equal to -1 then
    // in that case return the minimum of
    // them to the its parent
    if (left != -1 && right != -1)
        return min(left, right);
 
    // In case if the left child's value is
    // not equal to -1 BUT its right child's
    // value is equal to -1 then in that case
    // send the left child value to its
    // parent node.
    else if (left != -1)
        return left;
 
    // In case if the right child's value is
    // not equal to -1 BUT its left child's
    // value is equal to -1 then in that case
    // send the right child value to its
    // parent node.
    else
        return right;
}
 
// Driver code
int main()
{
    // Creating the root node
    /*         2
              / \
             2   5
                / \
               5   7 */
    struct Node* root = new Node(2);
    root->left = new Node(2);
    root->right = new Node(5);
    root->right->left = new Node(5);
    root->right->right = new Node(7);
 
    int SecondMinimumValue
        = findSecondMinimumValue(root);
    cout << SecondMinimumValue << endl;
    return 0;
}
输出
5

时间复杂度: O(H),其中 H 是树的高度
辅助空间: O(1)