菜🐔的学习之路java
掘金首页node
给定一个非空特殊的二叉树,每一个节点都是正数,而且每一个节点的子节点数量只能为 2 或 0。若是一个节点有两个子节点的话,那么该节点的值等于两个子节点中较小的一
个。
更正式地说,root.val = min(root.left.val, root.right.val) 总成立。
给出这样的一个二叉树,你须要输出全部节点中的第二小的值。若是第二小的值不存在的话,输出 -1 。
示例 1:
输入:root = [2,2,5,null,null,5,7]
输出:5
解释:最小的值是 2 ,第二小的值是 5 。
示例 2:
输入:root = [2,2,2]
输出:-1
解释:最小的值是 2, 可是不存在第二小的值。
提示:
树中节点数目在范围 [1, 25] 内
1 <= Node.val <= 231 - 1
对于树中每一个节点 root.val == min(root.left.val, root.right.val)
Related Topics 树 深度优先搜索 二叉树
👍 159 👎 0
复制代码
leetcode题目连接git
代码连接github
思路一:DFSmarkdown
public int findSecondMinimumValue(TreeNode root) {
//corner case
PriorityQueue<Integer> priorityQueue = new PriorityQueue<Integer>(new Comparator<Integer>() {
//小根堆
@Override
public int compare(Integer o1, Integer o2) {
if (o1 > o2) return 1;
return o1.equals(o2) ? 0 : -1;
}
});
dfs(root, priorityQueue);
if (priorityQueue.size() >= 2) {
int min = priorityQueue.poll();
while (priorityQueue.peek()!=null){
if (priorityQueue.peek()>min){
return priorityQueue.poll();
}else{
priorityQueue.poll();
}
}
}
return -1;
}
private void dfs(TreeNode root, PriorityQueue<Integer> queue) {
if (root == null) {
return;
}
queue.add(root.val);
dfs(root.left, queue);
dfs(root.right, queue);
}
复制代码
时间复杂度O(n)app
set写法ide
private void dfs(TreeNode root, Set<Integer> queue) {
if (root == null) {
return;
}
queue.add(root.val);
dfs(root.left, queue);
dfs(root.right, queue);
}
public int findSecondMinimumValue(TreeNode root) {
//corner case
Set<Integer> set = new TreeSet<>(new Comparator<Integer>() {
//小根堆
@Override
public int compare(Integer o1, Integer o2) {
if (o1 > o2) return 1;
return o1.equals(o2) ? 0 : -1;
}
});
dfs(root, set);
if (set.size() >= 2) {
int i = 0;
for (int num:set
) {
if (i == 1){
return num;
}else{
i++;
}
}
}
return -1;
}
复制代码
时间复杂度O(n)oop
思路二:dfs+剪枝学习
public int findSecondMinimumValue(TreeNode root) {
//corner case
if (root.left == null){
return -1;
}
Set<Integer> set = new TreeSet<>(new Comparator<Integer>() {
//小根堆
@Override
public int compare(Integer o1, Integer o2) {
if (o1 > o2) return 1;
return o1.equals(o2) ? 0 : -1;
}
});
set.add(root.left.val);
set.add(root.right.val);
if (root.left.val == root.val) {
dfs3(root.left, set);
}
if (root.right.val == root.val) {
dfs3(root.right, set);
}
if (set.size() >= 2) {
int i = 0;
for (int num : set
) {
if (i == 1) {
return num;
} else {
i++;
}
}
}
return -1;
}
private void dfs3(TreeNode root, Set<Integer> set) {
if (root == null) {
return;
}
if (root.left == null) {
return;
}
set.add(root.left.val);
set.add(root.right.val);
if (root.left.val == root.val) {
dfs3(root.left, set);
}
if (root.right.val == root.val) {
dfs3(root.right, set);
}
}
复制代码
时间复杂度O(n)优化
思路三:剪枝的进一步优化
其实以前解题时里想到过这种思路
可是仍是没有抓住重点就没继续往下思考
这种思路的依靠的条件有两个
这样的逻辑也就保证了ans只会在遇到了比最小值大的节点的时才会更新
同时ans更新后没必要再向下遍历
剪枝的进一步优化-剪掉全部子节点
int ans = -1;
public int findSecondMinimumValue(TreeNode root) {
dfs(root, root.val);
return ans;
}
void dfs(TreeNode root, int cur) {
if (root == null) return ;
if (root.val != cur) {
if (ans == -1) ans = root.val;
else ans = Math.min(ans, root.val);
return ;
}
dfs(root.left, cur);
dfs(root.right, cur);
}
复制代码
时间复杂度O(n)