给定一个非空特殊的二叉树,每个节点都是正数,并且每个节点的子节点数量只能为 2 或 0。
    如果一个节点有两个子节点的话,那么该节点的值等于两个子节点中较小的一个。
    更正式地说,即 root.val = min(root.left.val, root.right.val) 总成立。
    给出这样的一个二叉树,你需要输出所有节点中的 第二小的值 。
    如果第二小的值不存在的话,输出 -1 。

    示例 1:
    输入:root = [2,2,5,null,null,5,7]

    1. 2
    2. / \
    3. 2 5
    4. / \
    5. 5 7

    输出:5
    解释:最小的值是 2 ,第二小的值是 5 。

    示例 2:
    输入:root = [2,2,2]

    1. 2
    2. / \
    3. 2 2

    输出:-1
    解释:最小的值是 2, 但是不存在第二小的值。

    如果需要找到二叉树中节点的最大值该如何查找(1 <= Node.val <= 2³¹ - 1)?

    1. int maxVal = -1;
    2. public int findMaxValue(TreeNode root) {
    3. order(root);
    4. return maxVal;
    5. }
    6. private void order(TreeNode node) {
    7. if (node == null) {
    8. return;
    9. }
    10. if (node.val > maxVal) {
    11. maxVal = node.val;
    12. }
    13. order(node.left);
    14. order(node.right);
    15. }

    如果需要找到二叉树中节点的第二大值该如何查找(1 <= Node.val <= 2³¹ - 1)?

    1. int maxVal = -1;
    2. int secondMaxVal = -1;
    3. public int findSecondMaxValue(TreeNode root) {
    4. order(root);
    5. return secondMaxVal;
    6. }
    7. private void order(TreeNode node) {
    8. if (node == null) {
    9. return;
    10. }
    11. if (node.val > maxVal) {
    12. // 若当前值比已知最大值大,则将原最大值赋值给第二大值,将当前值作为新的最大值
    13. secondMaxVal = maxVal;
    14. maxVal = node.val;
    15. } else {
    16. // 若当前值没有比已知最大值大
    17. if (node.val != maxVal && node.val > secondMaxVal) {
    18. // 若当前值和已知最大值不相等,且比第二大值大,则将当前值作为新的第二大值
    19. secondMaxVal = node.val;
    20. }
    21. }
    22. order(node.left);
    23. order(node.right);
    24. }

    同理如何找到二叉树的最小值呢(1 <= Node.val <= 2³¹ - 1)?

    1. int minVal = Integer.MAX_VALUE;
    2. public int findMinValue(TreeNode root) {
    3. order(root);
    4. return minVal;
    5. }
    6. private void order(TreeNode node) {
    7. if (node == null) {
    8. return;
    9. }
    10. if (node.val < minVal) {
    11. minVal = node.val;
    12. }
    13. order(node.left);
    14. order(node.right);
    15. }

    那么同理可以找到二叉树的第二小值(1 <= Node.val <= 2³¹ - 1)?

    1. int minVal = Integer.MAX_VALUE;
    2. int secondMinVal = Integer.MAX_VALUE;
    3. public int findSecondMinimumValue(TreeNode root) {
    4. order(root);
    5. if (!isSecondMinValChange) {
    6. return -1;
    7. }
    8. return secondMinVal;
    9. }
    10. private void order(TreeNode node) {
    11. if (node == null) {
    12. return;
    13. }
    14. if (node.val < minVal) {
    15. secondMinVal = minVal;
    16. minVal = node.val;
    17. } else {
    18. if (node.val != minVal && node.val < secondMinVal) {
    19. secondMinVal = node.val;
    20. }
    21. }
    22. order(node.left);
    23. order(node.right);
    24. }

    测试时有个测试用例无法通过,root = [2,2,2],因为所有的节点值都相同,所以 secondMinVal 还是 Interger.MAX_VALUE
    所以需要标记一下 secondMinVal 是否发生过修改

    1. int minVal = Integer.MAX_VALUE;
    2. int secondMinVal = Integer.MAX_VALUE;
    3. boolean isSecondMinValChange = false;
    4. public int findSecondMinimumValue(TreeNode root) {
    5. order(root);
    6. if (!isSecondMinValChange) {
    7. return -1;
    8. }
    9. return secondMinVal;
    10. }
    11. private void order(TreeNode node) {
    12. if (node == null) {
    13. return;
    14. }
    15. if (node.val < minVal) {
    16. secondMinVal = minVal;
    17. minVal = node.val;
    18. } else {
    19. if (node.val != minVal && node.val < secondMinVal) {
    20. secondMinVal = node.val;
    21. isSecondMinValChange = true;
    22. }
    23. }
    24. order(node.left);
    25. order(node.right);
    26. }

    测试时有个测试用例无法通过,root = [2,2,2147483647],因为右节点值和 secondMinVal 相同,导致以为 secondMinVal 没有发生修改,
    所以需要修改一下判断 node.val != minVal && node.val < secondMinVal 改为 node.val != minVal && node.val <= secondMinVal

    1. int minVal = Integer.MAX_VALUE;
    2. int secondMinVal = Integer.MAX_VALUE;
    3. boolean isSecondMinValChange = false;
    4. public int findSecondMinimumValue(TreeNode root) {
    5. order(root);
    6. if (!isSecondMinValChange) {
    7. return -1;
    8. }
    9. return secondMinVal;
    10. }
    11. private void order(TreeNode node) {
    12. if (node == null) {
    13. return;
    14. }
    15. if (node.val < minVal) {
    16. secondMinVal = minVal;
    17. minVal = node.val;
    18. } else {
    19. if (node.val != minVal && node.val <= secondMinVal) {
    20. secondMinVal = node.val;
    21. isSecondMinValChange = true;
    22. }
    23. }
    24. order(node.left);
    25. order(node.right);
    26. }

    但是本题有特殊性,本题其实已经限定根节点已经是最小值了,故只需要和根节点比较即可

    1. int minVal = -1;
    2. int rootValue;
    3. public int findSecondMinimumValue(TreeNode root) {
    4. rootValue = root.val;
    5. order(root);
    6. return minVal;
    7. }
    8. private void order(TreeNode node) {
    9. if (node == null) {
    10. return;
    11. }
    12. if (node.val > rootValue) {
    13. minVal = node.val;
    14. }
    15. order(node.left);
    16. order(node.right);
    17. }

    但是如果一直比较,minVal 可能会一直发生变化,而实际上只要保证 minVal 只修改一次,那么最终 minVal 就是第二小的值

    1. int minVal = -1;
    2. int rootValue;
    3. public int findSecondMinimumValue(TreeNode root) {
    4. rootValue = root.val;
    5. order(root);
    6. return minVal;
    7. }
    8. private void order(TreeNode node) {
    9. if (node == null) {
    10. return;
    11. }
    12. if (minVal != -1 && node.val >= minVal) {
    13. return;
    14. }
    15. if (node.val > rootValue) {
    16. minVal = node.val;
    17. }
    18. order(node.left);
    19. order(node.right);
    20. }