最小化更改以转换为根为 1 的树,偶数左孩子和奇数右孩子
给定一棵二叉树,任务是使用最小数量的递增-递减操作将该树转换为满足以下条件的树:
- 根节点始终为 1。
- 节点的每个左孩子都是偶数。
- 节点的每个右孩子都是奇数。
返回并打印最后所需的最小增量-减量操作数。
例子:
Input:
Output: 3
Explanation:
Since root is already 1, no change is needed at root
Left child of root node is 2, so no change is needed here.
Right child of root node is 2, so change it to 3, making a change of 1.
Left child of node 2 is 5, so change it to 4, making a change of 1.
Left child of node 3 is 6, so no change is needed here.
Right child of node 3 is 8, so change it to 9, making a change of 1.
Hence total changes needed is 3.
Input:
Output: 0
Explanation: The given tree already satisfies the given conditions.
方法:想法是根据以下观察改变每个不满足条件的节点:
- If the root node is not 1, we can keep decrementing it by 1 till it becomes 1. So root-1 operations needed here.
- If the current node is a left child, and it is odd, we can simply make it even by incrementing or decrementing by 1. So 1 operation is needed here.
- If the current node is a right child, and it is even, we can simply make it odd by incrementing or decrementing by 1. So 1 operation is needed here.
Therefore, simply traverse the given Tree and:
- Add root-1 operations to the answer if the root is not 1.
- Add the count of left child which are odd, to the answer
- Also add the count of right child which are even, to the answer.
基于上述思路,我们可以按照以下步骤进行 DFS 遍历:
- 递归遍历左右孩子。
- 检查访问节点的左值是否不为空且节点的左子值是否为奇数
- 将答案增加 1
- 检查访问节点的右值是否不为空且节点的右子值是否为偶数
- 将答案增加 1
- 检查访问节点的左值是否不为空且节点的左子值是否为奇数
- 再次递归调用左右节点,直到遍历整个树。
- 还要检查 root 是否不等于 1。
- 如果为真,则将 root_value – 1 添加到答案中。
- 在最后返回答案。
下面是上述方法的实现:
C++
// C++ code for the above approach
#include
using namespace std;
// To store the final changes needed
int count_of_changes;
struct Node {
int value;
struct Node *left, *right;
};
// Utility function to create new
// tree node
Node* newNode(int data)
{
Node* temp = new Node;
temp->value = data;
temp->left = temp->right = NULL;
return temp;
}
// DFS function to convert
// binary tree to proper tree
void dfs(Node* root)
{
// Check if given root is NULL
// base case
if (root == NULL)
return;
// Check if visited node's
// left value is not null and
// node's left child value is odd
// decrement its value by 1
if (root->left
&& root->left->value % 2 == 1) {
root->left->value -= 1;
count_of_changes++;
}
// Check if visited node's
// value is not null and node's
// right child value is even,
// increment its value by 1
if (root->right
&& root->right->value % 2 == 0) {
root->right->value += 1;
count_of_changes++;
}
// Recursive call for left node
dfs(root->left);
// Recursive call for right node
dfs(root->right);
}
// Function to find
// the min changes needed
int minCount(Node* root)
{
// Initial value for
// final changes needed
count_of_changes = 0;
// Base case to check
// if root is NULL
if (root == NULL)
return count_of_changes;
if (root->value != 1) {
// Add root_value - 1 to the ans
count_of_changes += root->value - 1;
// Set root->Value to 1
root->value = 1;
}
// DFS Function call
dfs(root);
// Return the final count
return count_of_changes;
}
// Driver Code
int main()
{
// Taking input
Node* root = newNode(1);
root->left = newNode(2);
root->right = newNode(2);
root->left->left = newNode(5);
root->right->left = newNode(6);
root->right->right = newNode(8);
// Function call
cout << minCount(root) << endl;
return 0;
}
3
时间复杂度: O(V),其中 V 是给定树中的顶点数
辅助空间: O(H),这是函数调用的堆栈大小,其中 H 是树的高度。