第六章 二叉树 part06
今日内容
● 654.最大二叉树
● 617.合并二叉树
● 700.二叉搜索树中的搜索
● 98.验证二叉搜索树 详细布置
654.最大二叉树
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public TreeNode constructMaximumBinaryTree(int[] nums) {
if(nums.length==0)
return null;
return traversal(nums,0,nums.length);
}
//涉及到二分的话 这里还是沿用左开右闭 统一左闭右开
public TreeNode traversal(int[] nums,int begin,int end){
//因为是左闭右开 所以end-begin<1的时候 就是没有元素
if(end-begin<1){
return null;
}
//只有一个元素
if(end-begin==1){
//因为是左闭右开 所以是nums[begin] 右开 最右边的一直都是无用的
return new TreeNode(nums[begin]);
}
//寻找切割点————即是从[begin,end)这个区间段最大的那个元素
int maxValue=Integer.MIN_VALUE;
int delimiter=0;
for(int i=begin;i<end;i++){
if(nums[i]>maxValue){
maxValue=nums[i];
delimiter=i;
}
}
TreeNode root=new TreeNode(nums[delimiter]);
//然后依次向左切 以及 向右切
root.left=traversal(nums,begin,delimiter);
root.right=traversal(nums,delimiter+1,end);
return root;
}
}
617.合并二叉树
这次是一起操作两个二叉树了
通过递归,二叉树的前序遍历—— 中左右
将树2 合并到 树1中。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public TreeNode mergeTrees(TreeNode root1, TreeNode root2) {
if(root1==null)
return root2;
if(root2==null)
return root1;
root1.val+=root2.val;
root1.left=mergeTrees(root1.left,root2.left);
root1.right=mergeTrees(root1.right,root2.right);
return root1;
}
}
700.二叉搜索树中的搜索
二叉搜索树的特性 递归方法
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
//考虑使用递归的方法 结合二叉树的前序遍历
public TreeNode searchBST(TreeNode root, int val) {
if(root==null)
return null;
if(root.val==val)
return root;
//前序遍历————中左右
//递归左子树 如果找到 就return
TreeNode leftRes=searchBST(root.left,val);
if(leftRes!=null){
return leftRes;
}
//否则递归右子树
return searchBST(root.right,val);
}
}
迭代方法
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
//使用迭代法 结合二叉搜索树的特性
public TreeNode searchBST(TreeNode root, int val) {
if(root==null){
return null;
}
TreeNode curNode=root;
while(curNode!=null){
if(curNode.val==val)
return curNode;
if(val<curNode.val){
curNode=curNode.left;
}
else
curNode=curNode.right;
}
return curNode;
}
}
98.验证二叉搜索树
这道题主要是利用二叉搜索树的特性——二叉搜索树它的中序遍历结果是升序的。
所以可以推断:只要我们将这棵树进行中序遍历,将其结果存储到数组中,只要其是升序的,那么我们就可以说他是二叉搜索树。
注意: 这里有一个我个人碰到的点:
在for循环中进行判断时,不能写成如下形式:(数值会溢出!!) 因为它极有可能是一个很大的正数减去一个负数。
for(int i=list.size()-1;i>0;i--){
if(list.get(i)-list.get(i-1)<=0)
return false;
}
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
//考虑利用二叉搜索树的特性 二叉搜索树-中序遍历左中右 遍历出来它是升序的
class Solution {
public boolean isValidBST(TreeNode root) {
if(root.left==null && root.right==null)
return true;
List<Integer> list=new ArrayList<>();
traversal(root,list);
//因为上面的if语句已经判断了仅有一个根节点的情况 所以接下来树至少有两个节点
for(int i=list.size()-1;i>0;i--){
if(list.get(i)<=list.get(i-1))
return false;
}
return true;
}
public void traversal(TreeNode node,List<Integer> list){
if(node==null){
return;
}
traversal(node.left,list);
list.add(node.val);
traversal(node.right,list);
}
}
第六章 二叉树part07
今日内容
● 530.二叉搜索树的最小绝对差
● 501.二叉搜索树中的众数
● 236. 二叉树的最近公共祖先 详细布置
530.二叉搜索树的最小绝对差
个人错误思想(自查):
看到这道题并且结合力扣上面给的两个示例,想当然认为最小绝对差一定是在当前节点与其左右子节点之间产生。 然而这是错误的。
比如一棵树如下图所示,其最少绝对差是236-227 这两者并不是在相邻的层之间。
错误的代码:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
//尝试迭代层序遍历 暴力搜索
//猜测两值之差的最小值 一定在 某个节点及其子节点之间产生
public int getMinimumDifference(TreeNode root) {
int minVal=Integer.MAX_VALUE;
Queue<TreeNode> queue=new LinkedList<>();
//层序遍历要使用队列
queue.offer(root);
while(!queue.isEmpty()){
//len 是queue的长度 另一方面指代的也是当前遍历的层数的所有节点数量
int len=queue.size();
while(len>0){
//获取当前层的节点
TreeNode curNode=queue.poll();
len--;
//如果有左子节点的话 入队
if(curNode.left!=null){
queue.offer(curNode.left);
//计算当前节点与其左子节点的差值 更新minVal的值
if(curNode.val-curNode.left.val<minVal){
minVal=curNode.val-curNode.left.val;
}
}
//右子节点操作同上
if(curNode.right!=null){
queue.offer(curNode.right);
//根据二叉搜索树的概念,右子节点的数值是要大于当前节点的值
if(curNode.right.val-curNode.val < minVal){
minVal=curNode.right.val-curNode.val;
}
}
}
}
return minVal;
}
}
其实正确的方法也很简单,就是直接将题中所给的二叉搜索树进行中序遍历,然后将其存入到数组中,依次再两两比较即可。
这里学习&实现直接在二叉搜索树中实现双指针。
具体思想看代码注释
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
TreeNode pre;
int minVal=Integer.MAX_VALUE;
public int getMinimumDifference(TreeNode root) {
traversal(root);
return minVal;
}
//直接在二叉搜索树中使用双指针。即一个指针指向当前节点,另一个指针指向当前节点的中序遍历的上一个结点
//因为只有在二叉搜索树中 使用双指针才能达到 将所有数值存入到数组中再两两比对的效果
public void traversal(TreeNode node){
if(node==null){
return;
}
//中序遍历 左中右
//左
traversal(node.left);
//中
if(pre!=null){
minVal=node.val-pre.val<minVal? (node.val-pre.val):minVal;
}
pre=node;
//右
traversal(node.right);
}
}
501.二叉搜索树中的众数
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
int MaxCount=0;
int count=0;
TreeNode pre=new TreeNode();
public int[] findMode(TreeNode root) {
List<Integer> resList=new ArrayList<>();
traversal(root,resList);
int[] result=new int[resList.size()];
for(int i=0;i<resList.size();i++){
result[i]=resList.get(i);
}
return result;
}
//考虑使用中序遍历 将二叉搜索树中的所有节点存入到list之中
public void traversal(TreeNode node,List<Integer> resList){
//中序遍历 左中右
//如果当前节点为空
if(node==null){
return;
}
//左
traversal(node.left,resList);
//中
//获取当前节点的数值
int curNodeVal=node.val;
//如果当前节点是第一个节点(pre==null) 或者节点的值发生了跳转
if(pre==null || curNodeVal!=pre.val){
count=1;
}
else{
count++;
}
//更新结果
if(count>MaxCount){
resList.clear();
MaxCount=count;
resList.add(node.val);
}
else if(count==MaxCount){
resList.add(node.val);
}
pre=node;
//右
traversal(node.right,resList);
}
}
236. 二叉树的最近公共祖先
难以理解