题目描述
有一棵二叉树,树上每个点标有权值,权值各不相同,请设计一个算法算出权值最大的叶节点到权值最小的叶节点的距离。二叉树每条边的距离为1,一个节点经过多少条边到达另一个节点为这两个节点之间的距离。
给定二叉树的根节点root,请返回所求距离。
解题思路
基本想法:首先遍历二叉树,找到最大最小叶节点的位置,然后找到两者的最小公共祖先(这里的最小祖先指的是位置最靠近两个节点的祖先)。
方法一:找到最大最小叶节点的位置需要遍历整个二叉树,寻找公共祖先可以从其中一个节点开始,向上追溯,并且标记访问过的节点,另一个节点在向上追溯的过程中,遇到被访问过的节点就可以停止,两个节点到达这一节点的步数和就是距离长度。
方法二:在寻找最大最小叶节点的时候同时记录其路径,然后比较两条路径,去掉公共部分,剩下的就是两个节点的距离。
代码实现
方法一:
#include <iostream>
#include <vector>
#include <limits>
using namespace std;
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};
class Tree {
public:
int getDis(TreeNode* root) {
// write code here
vector<int> indexs;
vector<int> weights;
int maxn_index,minn_index;
Traverse(root,indexs,weights,maxn_index,minn_index);
int distance=getDisByIndex(maxn_index,minn_index,indexs);
return distance;
}
void Traverse(TreeNode* root,vector<int>& indexs,vector<int>& weights,int& maxn_index,int& minn_index){
if(root==NULL) return;
vector<TreeNode*> nodes;
maxn_index=-1;
minn_index=-1;
int minn = numeric_limits<int>::max();
int maxn = numeric_limits<int>::min();
nodes.push_back(root);
indexs.push_back(-1);
weights.push_back(root->val);
TreeNode *left,*right,*current;
int i=-1;
while(!nodes.empty()){
current=nodes[0];
nodes.erase(nodes.begin());
i++;
left=current->left;
right=current->right;
if(left==NULL && right==NULL){
if(minn>current->val){
minn=current->val;
minn_index=i;
}
if(maxn<current->val){
maxn=current->val;
maxn_index=i;
}
}
if(left!=NULL){
nodes.push_back(left);
indexs.push_back(i);
weights.push_back(left->val);
}
if(right!=NULL){
nodes.push_back(right);
indexs.push_back(i);
weights.push_back(right->val);
}
}
}
int getDisByIndex(int maxn_index,int minn_index,vector<int>& indexs){
if(maxn_index==minn_index) return 0;
vector<int> visit;
int n=indexs.size();
visit.resize(n,-1);
int step=0;
int pmax,pmin;
pmax=maxn_index;
while(pmax!=-1){
if(visit[pmax]==-1){
visit[pmax]=step++;
pmax=indexs[pmax];
}
}
int cnt=0;
pmin=minn_index;
while(pmin!=-1){
if(visit[pmin]!=-1){
return cnt+visit[pmin];
}
pmin=indexs[pmin];
cnt++;
}
}
}
方法二:
#include <iostream>
#include <limits>
using namespace std;
struct TreeNode{
int val;
TreeNode *left,*right;
TreeNode(int x):val(x),left(NULL),right(NULL){}
}
class Solution{
public:
int minn,maxn;
vector<int> minn_path,maxn_path;
int getDis(TreeNode* root){
minn=limits<int>::max();
maxn=limits<int>::min();
vector<int> vec;
dfs(root,vec);
for(int i=0;;i++){
if(minn_path[i]==maxn_path[i])
continue;
else
return minn_path.size()-i+maxn_path.size();
}
}
void dfs(TreeNode* root,vector<int>& vec){
if(root==NULL)return;
if(root->left==NULL && root->right==NULL){
if(minn>root->val){
minn=root->val;
minn_path.assign(vec.begin(),vec.end());
}
if(maxn<root->val){
maxn=root->val;
maxn_path.assign(vec.begin(),vec.end());
}
}
vec.push_back(-1);
dfs(root->left,vec);
vec.pop_back();
vec.push_back(1);
dfs(root->right,vec);
vec.pop_back();
}
}
这道题的思路很清晰,理清楚就可以。但是笔者却花了半天时间,就是显示无法通过测试用例,我确信方法没问题,调试到怀疑人生。。。后来发现题目是最大最小叶节点,而我做的是最大最小节点!!!