给定一个非空特殊的二叉树,每个节点都是正数,并且每个节点的子节点数量只能为 2
或 0
。如果一个节点有两个子节点的话,那么这个节点的值不大于它的子节点的值。
给出这样的一个二叉树,你需要输出所有节点中的第二小的值。如果第二小的值不存在的话,输出 -1 。
示例 1:
输入: 2 / \ 2 5 / \ 5 7 输出: 5 说明: 最小的值是 2 ,第二小的值是 5 。
示例 2:
输入: 2 / \ 2 2 输出: -1 说明: 最小的值是 2, 但是不存在第二小的值。
一开始这题用的是深度优先搜索,虽然没有错,但是却没有利用好题目所给的条件,效率不高。
题目所给的函数原型为int findSecondMinimumValue(TreeNode* root) ,对于这样一个函数,可以这样理解:返回值是与root->val不同的值。分四种情况:
1、如果root的值与左右孩子的值各不相同,那么返回的是左右孩子的最小值
2、如果root的值与左孩子值相同,且与右孩子值不同。那么,只要递归调用左孩子得到的返回值不为-1,那么答案就是返回值与右孩子值的最小值。否则,答案就是右孩子的值
3、与第二种情况左右相反
4、如果root的值与左右孩子的值都相同,那么返回的是递归调用左右孩子的返回值的最小值。如果有返回值是-1,那么结果是另一个返回值(即使也有可能是-1)
总之,利用好题目条件,可以画图找一下规律
我的代码如下,很丑陋,但是比较好理解
class Solution {
public:
int findSecondMinimumValue(TreeNode* root)
{
if(root->left)
{
if(root->left->val != root->val && root->right->val != root->val)
return min(root->left->val, root->right->val);
else if(root->left->val == root->val && root->right->val != root->val)
{
int left = findSecondMinimumValue(root->left);
if(left == -1)
return root->right->val;
else
return min(left, root->right->val);
}
else if(root->left->val != root->val && root->right->val == root->val)
{
int right = findSecondMinimumValue(root->right);
if(right == -1)
return root->left->val;
else
return min(right, root->left->val);
}
else if(root->left->val == root->val && root->right->val == root->val)
{
int left = findSecondMinimumValue(root->left);
int right = findSecondMinimumValue(root->right);
if(left == -1)
return right;
else if(right == -1)
return left;
else
return min(left, right);
}
}
else
return -1;
}
};
简洁的写法如下,参考https://blog.csdn.net/YTTmiao/article/details/78770217
public int findSecondMinimumValue4(TreeNode root) {
if (root.left != null && root.right != null) {
int left = root.left.val, right = root.right.val;
if (root.left.val == root.val) {
left = findSecondMinimumValue4(root.left);
}
if (root.right.val == root.val) {
right = findSecondMinimumValue4(root.right);
}
if (left != -1 && right != -1) {
return Math.min(left, right);
}
else return left == -1 ? right : left;
}
else return -1;
}