19. 最大二叉树
题目链接:654. 最大二叉树 - 力扣(LeetCode)
思路:前序遍历构造二叉树
- 找到最大值及其下标(最大值用于创建根,下标用于划分左右子树)
- 递归左子树
- 递归右子树
Code
class Solution {
public TreeNode constructMaximumBinaryTree(int[] nums) {
TreeNode root = dfs(nums, 0, nums.length - 1);
return root;
}
public TreeNode dfs(int[] nums, int l, int r){
if(l > r){
return null;
}
//1. 找出区间[l, r]最大值及其位置
int maxValue = -0x3f3f3f3f;
int idx = 0;
for(int i = l; i <= r; i ++){
if(nums[i] > maxValue){
maxValue = nums[i];
idx = i;
}
}
// 根
TreeNode root = new TreeNode(maxValue);
// 左
root.left = dfs(nums, l, idx - 1);
root.right = dfs(nums, idx + 1, r);
// 返回根节点
return root;
}
}
20. 合并二叉树
题目链接:617. 合并二叉树 - 力扣(LeetCode)
思路:前序遍历同时(同步)遍历两棵二叉树:
- 若当前
树1
的节点为空,则用树2
的当前节点 - 若当前
树2
的节点为空,则用树1
的当前节点 - 若当前两个树的当前节点不为空,则更新为两个节点值得和即可
按照上面得规则前序遍历创建二叉树,我们可以在
树1
的基础上改,或者新建一棵树用来拼接。
Code
在树1
的基础上修改:
class Solution {
public TreeNode mergeTrees(TreeNode root1, TreeNode root2) {
return dfs(root1, root2);
}
public TreeNode dfs(TreeNode root1, TreeNode root2){
if(root1 == null) return root2;
if(root2 == null) return root1;
// 根
root1.val += root2.val;
// 左
root1.left = dfs(root1.left, root2.left);
// 右
root1.right = dfs(root1.right, root2.right);
// 返回根节点
return root1;
}
}
新建一棵树用来记录:
class Solution {
public TreeNode mergeTrees(TreeNode root1, TreeNode root2) {
return dfs(root1, root2);
}
public TreeNode dfs(TreeNode root1, TreeNode root2){
if(root1 == null) return root2;
if(root2 == null) return root1;
// 根
TreeNode root = new TreeNode(0);
root.val = root1.val + root2.val;
// 左
root.left = dfs(root1.left, root2.left);
// 右
root.right = dfs(root1.right, root2.right);
// 返回根节点
return root;
}
}
21二叉搜索树中的搜索
思路:利用二叉搜索树:
- 任意左节点不为空 均不大于它的根节点
- 任意右节点不为空 均不小于它的根节点
我们利用该性质去便利二叉树即可,当前节点值小于 val 则去遍历右子树
大于则遍历左子树,反之则相等,返回
题目链接:700. 二叉搜索树中的搜索 - 力扣(LeetCode)
Code
/**
思路:利用二叉搜索树:
任意左节点不为空 均不大于它的根节点
任意右节点不为空 均不小于它的根节点
我们利用该性质去便利二叉树即可,当前节点值小于 val 则去遍历右子树
大于则遍历左子树,反之则相等,返回
*/
class Solution {
public TreeNode searchBST(TreeNode root, int val) {
return dfs(root, val);
}
public TreeNode dfs(TreeNode root, int val){
if(root == null || root.val == val){
return root;
}
return dfs(root.val < val ? root.right : root.left, val);
}
}
22.验证二叉搜索树
题目链接:98. 验证二叉搜索树 - 力扣(LeetCode)
思路:二叉搜索树的中序遍历是有序的(递增),因此我们只需要进行中序遍历,判断是否是有序的即可。
Code
class Solution {
List<Integer> list = new ArrayList<>();
public boolean isValidBST(TreeNode root) {
dfs(root);
for(int i = 1; i < list.size(); i ++){
if(list.get(i) <= list.get(i - 1)){
return false;
}
}
return true;
}
// 中序:左根右
public void dfs(TreeNode root){
if(root == null){
return ;
}
dfs(root.left);
list.add(root.val);
dfs(root.right);
}
}
上面的解法额外开了O(n)
的空间,我们可以用一个变量(last_val
)来记录当前节点的上一个元素值(中序的),如果当前值 > last_val
,说明可以继续往下遍历,反之说明中序遍历不是有序的!,一棵树是二叉搜索树,那么它的左右子树也必定得是二叉搜索树。
Code
class Solution {
long last_val = Long.MIN_VALUE;
public boolean isValidBST(TreeNode root) {
return dfs(root);
}
// 中序:左根右
public boolean dfs(TreeNode root){
if(root == null) return true;
// 左
if(!dfs(root.left)) return false;
// 根
if(root.val <= last_val) return false;
else last_val = root.val;
// 右
return dfs(root.right);
}
}