给定二叉树的第二个唯一最小值,其每个节点都是其子节点中的最小值
给定一个完整的二叉树,其中每个节点的值与其子节点之间的最小值相同,任务是找到树的第二个最小唯一值。
例子:
Input: tree:
Output: 5
Explanation: All the unique values present in the tree are 2, 5 and 7.
The second smallest is 5.
Input: tree:
Output: -1
Explanation: All the numbers present in the tree are same.
There is no other value except 2, so second smallest is not possible.
Naive Approach:解决问题的基本方法是基于以下思想:
Store all the unique values in an array and sort the array. Then find the second minimum from the array.
请按照以下步骤更清楚地了解该方法:
- 遍历树并将所有值存储在一个数组中。
- 对数组进行排序。
- 遍历数组并找到不等于数组最小元素的第一个数组元素(即索引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)
有效的方法:通过使用以下观察可以有效地解决问题:
The root node of the tree contains the minimum among all the nodes.
If the value of all the nodes with minimum value is replaced by some other arbitary numbers out of the range of tree values and the tree property is maintained then the root node will have the current minimum value which is actually the second minimum of the given tree.
上述观察可以使用递归来实现。按照下面提到的方法来实现上述观察的想法:
- 使用递归函数遍历树并实现观察。
- 在任何节点的每次递归中:
- 找出它的哪个孩子与根具有相同的值,并为该孩子调用下一个递归。
- 如果当前节点的值与根相同并且没有任何子节点,或者两个子节点的值相同,则将其值替换为-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)