在二叉树中查找字典上最小的直径
给定一个节点值是小写字母的二叉树,任务是找到字典上最小的直径。直径是任何两个叶节点之间的最长路径,因此,二叉树中可以有多个直径。任务是打印所有可能直径中按字典顺序排列的最小直径。
例子:
Input:
a
/ \
b c
/ \ / \
d e f g
Output: Diameter: 5
Lexicographically smallest diameter: d b a c f
Explanation:
Note that there are many other paths
exist like {d, b, a, c, g},
{e, b, a, c, f} and {e, b, a, c, g}
but {d, b, a, c, f}
is lexicographically smallest
Input:
k
/ \
e s
/ \
g f
Output: Diameter: 4
Lexicographically smallest diameter: f e k s
Explanation:
Note that many other paths
exist like {g, e, k, s}
{s, k, e, g} and {s, k, e, f}
but {f, e, k, s} is
lexicographically smallest
方法:
该方法类似于上一篇文章中讨论的查找直径。现在来了
打印具有最大直径和字典最小的最长路径。
脚步:
- 自定义比较函数返回按字典顺序排列的最小向量。
- 维护了六种向量,其中包含
leftdiameter 中的左子树(节点的)节点
rightdiameter 中的右子树(节点的)节点
出现在(节点的)左侧高度的节点
节点出现在(节点的)正确高度
heightv 向量包含出现最大高度路径的节点
直径向量包含出现最大高度路径的节点 - 其余部分在代码注释中解释,这里很难用文字解释
下面是上述方法的实现:
CPP
// C++ program for the above approach
#include
using namespace std;
// Binary Tree Node
struct node {
char data;
node *left, *right;
};
// Utility function to create a new node
node* newNode(char data)
{
node* c = new node;
c->data = data;
c->left = c->right = NULL;
return c;
}
// Function to compare and return
// lexicographically smallest vector
vector compare(vector a, vector b)
{
for (int i = 0; i < a.size() && i < b.size(); i++) {
if (a[i]->data < b[i]->data) {
return a;
}
if (a[i]->data > b[i]->data) {
return b;
}
}
return a;
}
// Function to find diameter
int diameter(node* root, int& height, vector& dia,
vector& heightv)
{
// If root is null
if (!root) {
height = 0;
return 0;
}
// Left height and right height
// respectively
int lh = 0, rh = 0;
// Left tree diameter and
// right tree diameter
int ld, rd;
vector leftdia;
vector rightdia;
vector leftheight;
vector rightheight;
// Left subtree diameter
ld = diameter(root->left, lh, leftdia, leftheight);
// Right subtree diameter
rd = diameter(root->right, rh, rightdia, rightheight);
// If left height is more
// than right tree height
if (lh > rh) {
// Add current root so lh + 1
height = lh + 1;
// Change vector heightv to leftheight
heightv = leftheight;
// Insert current root in the path
heightv.push_back(root);
}
// If right height is
// more than left tree height
else if (rh > lh) {
// Add current root so rh + 1
height = rh + 1;
// Change vector heightv to rightheight
heightv = rightheight;
// Insert current root in the path
heightv.push_back(root);
}
// Both height same compare
// lexicographically now
else {
// Add current root so rh + 1
height = rh + 1;
// Lexicographical comparison between two vectors
heightv = compare(leftheight, rightheight);
// Insert current root in the path
heightv.push_back(root);
}
// If distance of one leaf node to another leaf
// containing the root is more than the left
// diameter and right diameter
if (lh + rh + 1 > max(ld, rd)) {
// Make dia equal to leftheight
dia = leftheight;
// Add current root into it
dia.push_back(root);
for (int j = rightheight.size() - 1; j >= 0; j--) {
// Add right tree (right to root) nodes
dia.push_back(rightheight[j]);
}
}
// If either leftdiameter containing the left
// subtree and root or rightdiameter containing
// the right subtree and root is more than
// above lh+rh+1
else {
// If diameter of left tree is
// greater our answer vector i.e
// dia is equal to leftdia then
if (ld > rd) {
dia = leftdia;
}
// If both diameter
// same check lexicographically
else if (ld == rd) {
dia = compare(leftdia, rightdia);
}
// If diameter of right tree
// is greater our answer vector
// i.e dia is equal to rightdia then
else {
dia = rightdia;
}
}
return dia.size();
}
// Driver code
int main()
{
node* root = newNode('a');
root->left = newNode('b');
root->right = newNode('c');
root->left->left = newNode('d');
root->left->right = newNode('e');
root->right->left = newNode('f');
root->right->right = newNode('g');
int height = 0;
vector dia, heigh;
cout << "Diameter is: " << diameter(root, height,
dia, heigh)
<< endl;
// Printing the lexicographically smallest diameter
cout << "Lexicographically smallest diameter:" << endl;
for (int j = 0; j < dia.size(); j++) {
cout << dia[j]->data << " ";
}
return 0;
}
输出:
Diameter is: 5
Lexicographically smallest diameter:
d b a c f