文章:代码随想录
最大二叉树:
思路:
这道题其实就是day16中后序构建二叉树的简易版,有了昨天的思路这题很容易做.
代码:
public TreeNode constructMaximumBinaryTree(int[] nums) {
if(nums.length==0){return null;}
//左闭右开
return getTree(nums,0,nums.length);
}
private TreeNode getTree(int[] nums, int start, int end) {
if(start==end) return null;
int maxIndex=0;
int max=-1;
for (int i = start; i <end ; i++) {
if(nums[i]>max){max=nums[i]; maxIndex=i;}
}
TreeNode node=new TreeNode(max);
//定义左子树区间范围
int leftStart=start;
int leftEnd=maxIndex;
//定义右子树区间范围
int rightStart=maxIndex+1;
int rightEnd=end;
node.left=getTree(nums,leftStart,leftEnd);
node.right=getTree(nums,rightStart,rightEnd);
return node;
}
合并二叉树:
思路:
其实就是同时遍历两棵二叉树,将两个都不为空的节点值相加生成一颗新的节点,如果有一颗相同节点位置的树节点为空,另一棵不为空,那么就直接返回/指向另一颗不为空的树节点就行,因为空和不为空的节点值相加,其实就是不为空的节点本身.
代码:
//前序遍历
public TreeNode mergeTrees(TreeNode root1, TreeNode root2) {
if(root1==null && root2==null){return null;}
//因为没有说一点是相同深度的二叉树相合并,那么就说明可能存在有第一棵树左边还有,但是右边的树左边没有了.
//这里的逻辑是当这种情况发生时,其实直接返回有的那一边子树就可以了.因为如果另一颗树没有了,接下来的所有数值的和其实也就是这颗树的本身.
if(root1==null){return root2;}
if(root2==null){return root1;}
//创建一个新节点
TreeNode node=new TreeNode();
node.val=root1.val+root2.val;
node.left=mergeTrees(root1.left,root2.left);
node.right=mergeTrees(root1.right,root2.right);
return node;
}
//用栈迭代法,用队列也行(都是两两抛出比较) 前序遍历
//这里思路是直接改变root1的结构,最后返回root1.
public TreeNode mergeTreesLevel(TreeNode root1, TreeNode root2) {
if (root1 == null) {
return root2;
}
if (root2 == null) {
return root1;
}
Stack<TreeNode> stack = new Stack<>();
stack.push(root2);
stack.push(root1);
while (!stack.isEmpty()) {
TreeNode node1 = stack.pop();
TreeNode node2 = stack.pop();
node1.val += node2.val;
//因为用栈模拟,所以先右后左
//判断右子树情况
if (node2.right != null && node1.right != null) {
stack.push(node2.right);
stack.push(node1.right);
} else {
if (node1.right == null) {
node1.right = node2.right;
}
}
//判断左子树情况
if (node2.left != null && node1.left != null) {
stack.push(node2.left);
stack.push(node1.left);
} else {
if (node1.left == null) {
node1.left = node2.left;
}
}
}
return root1;
}
二叉搜索树中的搜索树:
这里主要是要明白搜索树的特性以及利用,利用二叉树特性可以写出更简洁的代码.
二叉搜索树特性:
左子树所有节点的元素值均小于根的元素值;右子树所有节点的元素值均大于根的元素值。
我原本不知道二叉树的特性时写的代码如下:
//自写初代版,没利用特性
public TreeNode searchBST(TreeNode root, int val) {
if(root==null)return null;
if(root.val==val){return root;}
TreeNode left=searchBST(root.left,val);
TreeNode right=searchBST(root.right,val);
if(left!=null) return left;
if(right !=null) return right;
return null;
}
后面可以根据特性写出递归和迭代法:
因为它本来就是二叉搜索树了,所以如果当前节点比目标值小,则往大的方向找,也就是往右子树找,反之则往左子树找.
//利用特性 递归版
//若 root 为空则返回空节点;
//若 val=root.val,则返回 root;
//若 val<root.val.递归左子树;
//若 val>root.val,递归右子树
public TreeNode searchBSTR1(TreeNode root, int val) {
if(root==null)return null;
if(root.val==val) return root;
return root.val<val?searchBST(root.right,val):searchBST(root.left,val);
}
//迭代法,利用二叉树特性
public TreeNode searchBSTT2(TreeNode root, int val) {
if(root==null) return null;
while(root!=null){
if(root.val==val) return root;
root=val>root.val?root.right:root.left;
}
return null;
}
验证二叉搜索树:
思路:
其实也是要利用二叉搜索树的特性:
中序遍历这颗树的话,得到的结果是有序的。
直白想法:
将中序遍历的结果存在数组中,最后判断这个数组是不是无重复升序的. 但是这样性能很差,不是最优解。
代码:
ArrayList<Integer> result=new ArrayList<>();
void inTraversal(TreeNode root){
if(root==null) return;
inTraversal(root.left);
result.add(root.val);
inTraversal(root.right);
}
public boolean isValidBST(TreeNode root) {
inTraversal(root);
Boolean flag=true;
for(int i=1;i<result.size();i++){
if(result.get(i)<=result.get(i-1)) flag=false;
}
return flag;
}
双指针优化:
做一个优化,在递归迭代的过程中就可以去比较是不是单调递增的,因为中序遍历的过程种就可以比较. 做一个双指针优化,用一个指针指向上一个节点,这样中序遍历的过程中就可以比较;
注意得是中序遍历
代码:
TreeNode pre=null;
public boolean isValidBSTDouble(TreeNode root) {
if(root==null){return true;}
Boolean left=isValidBSTDouble(root.left);
//前一个必须小于目前的节点
if(pre!=null && pre.val>=root.val)return false;
pre=root;
Boolean right=isValidBSTDouble(root.right);
return left && right;
}
迭代版本:
//迭代法:
public boolean isValidBSTStack(TreeNode root) {
if(root == null) return true;
Stack<TreeNode> stack = new Stack<>();
TreeNode pre = null;
stack.add(root);
while(!stack.isEmpty()){
TreeNode curr = stack.pop();
if(curr != null){
if(curr.right != null)
stack.add(curr.right);
stack.add(curr);
stack.add(null);
if(curr.left != null)
stack.add(curr.left);
}else{
//cur等于null的时候开始弹出
TreeNode temp = stack.pop();
//pre值必须更小,pre如果更大则不是升序
if(pre != null && pre.val >= temp.val)
return false;
pre = temp;
}
}
return true;
}