题目描述
请设计一个算法,寻找二叉树中指定结点的下一个结点(即中序遍历的后继)。
给定树的根结点指针TreeNode* root和结点的值int p,请返回值为p的结点的后继结点的值。保证结点的值大于等于零小于等于100000且没有重复值,若不存在后继返回-1。
方式一:中序遍历树,将树中节点的值保存到vector中,再遍历一遍vector,找到指定的值的下一个。
树的定义:
struct TreeNode
{
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x):val(x),left(NULL),right(NULL)
{
}
};
void InOrder(TreeNode *root,vector<int> & v)
{
if(root == NULL)
return ;
InOrder(root->left,v);
v.push_back(root->val);
InOrder(root->right,v);
}
int FindSucc(TreeNode *root,int p)
{
if(root == NULL || p < 0)
return -1;
vector<int>v ; //因为题目中说没有重复的值,所以想到用vector保存所有的值
InOrder(root,v);
for(int i = 0; i < v.size()-1; ++i) //如果是最后一个节点,没有后继。
{
if(v[i] == p)
return v[i+1];
}
return -1;
}
方式二:
要寻找中序遍历的某个节点的下一个节点,肯定是要通过中序遍历实现的,题目中明确告诉我们节点的值没有重复,所以只要在中序遍历的过程中,某个节点的值等于p,则告诉递归者下一个要遍历的节点便是我们要找的节点,这个需要有个信号在多次递归之间进行传递消息,c++里用引用完全可以实现,只需要传递一个整型或bool类型的引用便可。
int InOrder(TreeNode *root,int p,int &sign)
{
if(root == NULL)
return -1;
//遍历左子树。
int left = InOrder(root->left,p,sign);
if(left != -1) //不等于-1,表示查找到了,这里一定要有if,这里是查找
return left; //查找是左子树查不到,就去右子树查找,当左子树查找到了,没有必要再去右子树了,直接return .查不到一定还要记得去右子树查找。
//跟
if(sign == 1) //这两句话有顺序,别乱写
return root->val;
if(root->val == p)
sign = 1;
//右子树
return InOrder(root->left,p,sign); //查找右子树是最后一步,这里就没有必要if判断了。直接就可以返回,找到了返回后继节点,找不到返回-1.
}
int FindSucc(TreeNode *root,int p)
{
if(root == NULL || p < 0)
return -1;
int sign = 0;
return InOrder(root,p,sign);
}
void test()
{
TreeNode *p1 = new TreeNode(3);
TreeNode *p2 = new TreeNode(5);
TreeNode *p3 = new TreeNode(4);
TreeNode *p4 = new TreeNode(2);
TreeNode *p5 = new TreeNode(1);
TreeNode *p6 = new TreeNode(8);
p1->left = p2;
p1->right = p3;
p2->left = p4;
p2->right = p5;
p3->right = p6;
int val = FindSucc(p1,5);
cout << "val = " << val <<endl;
}
int main()
{
test();
cout << "hello..."<<endl;
return 0;
}