1、验证二叉搜索树:节点的左子树只包含小于当前节点的数,右子树只包含大于当前节点的数
2、对称二叉树
3、二叉树的层序遍历
二叉树的结构
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(){
}
TreeNode(int val){
this.val=val;
}
TreeNode(int val, TreeNode right, TreeNode left){
this.val=val;
this.left=left;
this.right=right;
}
}
这题一开始想的就是采用递归,但是最开始想的简单递归,用例没有通过,显然忘了二叉搜索树的最重要的定义,最后看了题解,知道这个递归需要加一个范围值。递归时候就将这个范围也递归下去。
/**
* 方法一:采用递归做
*描述: 一开始我做的时候只是判断了一个节点的左子树和右子树是否满足了二叉树的需要,
* 并没有再深层次的判断,所以是错误的。这里需要设置节点的范围
* 验证二叉搜索树
* @param root
* @return
* 执行用时:0ms,内存消耗:40.8MB
*/
public boolean isValidBST(TreeNode root) {
return isValidBst(root,Long.MIN_VALUE,Long.MAX_VALUE);
}
public boolean isValidBst(TreeNode root,long minVal,long maxVal){
if(root==null)
return true;
if(root.val>=maxVal||root.val<=minVal)
return false;
return isValidBst(root.left,minVal,root.val)&& isValidBst(root.right,root.val,maxVal);
}
这题的还有一种方法就是利用二叉树的中序遍历,中序遍历出的数肯定是升序的。中序遍历有递归和非递归两种方式。递归的方式简单,这里就不再介绍,所以采用的是非递归的方式。
/**
* 方法二:利用中序遍历的非递归
* 思路:对于二叉搜索树来说,中序遍历的节点肯定是有序的,所以只要中序遍历后。
* 判断当前节点是否比前一个节点小
* @param root
* @return
* 执行用时:2ms,内存消耗:41.1MB。
*/
public boolean isValidBST2(TreeNode root) {
TreeNode temp=null;
Stack<TreeNode> stack=new Stack<>();
//这里需要加上一个栈的判断,因为有时候会节点为null的情况
while(root!=null||!stack.isEmpty()){
//while循环将左节点压入堆栈中
while(root!=null){
stack.push(root);
root=root.left;
}
if(!stack.isEmpty()){
root = stack.pop();
if(temp!=null&&temp.val>=root.val)
return false;
temp=root;
root =root.right;
}
}
return true;
}
这题一开始我想的方法很简单,就是采用两个栈结构。都是将二叉树的节点依次进栈和出栈。但是一个栈是左节点先进栈,另一个栈是右节点先进栈。
/**
* 方法一:利用两个栈结构,解决
* 思路:两个栈结构,一个栈结构先放左节点,后放右节点
* 另一个先放右节点,再放左节点。然后依次比较两个栈中数据的值
* @param root
* @return
* 执行用时:1ms,内存消耗:39.5MB
*/
public boolean isSymmetric(TreeNode root) {
if(root==null)
return true;
Stack<TreeNode> stack1=new Stack<>();
Stack<TreeNode> stack2=new Stack<>();
stack1.push(root);
stack2.push(root);
while(!stack1.isEmpty()&&!stack2.isEmpty()){
TreeNode pop1 = stack1.pop();
TreeNode pop2 = stack2.pop();
if(pop1.val!= pop2.val)
return false;
if(pop1.left!=null){
stack1.push(pop1.left);
}else{
if(pop2.right!=null)
return false;
}
if(pop1.right!=null){
stack1.push(pop1.right);
}else{
if(pop2.left!=null)
return false;
}
if(pop2.right!=null){
stack2.push(pop2.right);
}
if(pop2.left!=null){
stack2.push(pop2.left);
}
}
return true;
}
第二种方法就是这个算法的最优解,采用递归的方式。
/**
* 最优解
* 方法二:使用递归进行计算
* 思路:一个节点的左节点的左节点必须和右节点的右节点相等,
* 一个节点的左节点的右节点必须和左节点的右节点相等
* @param root
* @return
* 执行用时:0ms,内存消耗:39.7MB
*/
public boolean isSymmetric2(TreeNode root) {
if(root==null)
return true;
return isSymmetricHelper(root.left,root.right);
}
public boolean isSymmetricHelper(TreeNode left,TreeNode right){
if(left==null&&right==null)
return true;
if(left==null||right==null||left.val!=right.val){
return false;
}
return isSymmetricHelper(left.left,right.right)&&isSymmetricHelper(left.right,right.left);
}
这题很简单,就是利用一个队列来进行层序遍历。
/**
* 方法一:利用层序遍历每次增加,就往里面加一个list的值
* 思路: 这题主要是考二叉树的层序遍历,利用数据结构的队列的先进先出的例子进行增加list中的值
* @param root
* @return
* 执行用时:1ms,内存消耗:41.4MB
*/
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> resultList=new ArrayList<>();
LinkedList<TreeNode> queue=new LinkedList<>();
if (root==null)
return resultList;
queue.addLast(root);
while(queue.size()!=0){
List<Integer> tempList=new ArrayList<>();
int size=queue.size();
while(size!=0){
TreeNode tempNode = queue.removeFirst();
tempList.add(tempNode.val);
size--;
if(tempNode.left!=null){
queue.addLast(tempNode.left);
}
if(tempNode.right!=null){
queue.addLast(tempNode.right);
}
}
resultList.add(tempList);
}
return resultList;
}