二叉树理论基础
满二叉树:总共有k层,则节点总数为2^k - 1。根节点为第一层。
完全二叉树:除了最后一层,其余的都是满二叉树。并且最后一层从左到右连续。
二叉搜索树:搜索时间复杂度
平衡二叉搜索树:左右子树的高度差不能超过1。诸如C++里的map、set容器的实现原理就是平衡二叉树。
存储方式:
链式存储
线性存储:左孩子:2i+1;右孩子:2i+2
遍历方式:
1.深度优先搜索(二叉树的前、中、后序遍历)
利用递归的方式实现。也可利用迭代法实现。
2.广度优先搜索(层序遍历)
利用迭代法实现。依赖队列实现。
leetcode 144 二叉树的前序遍历
注意将结果数组定义到执行函数的外部作为类的成员属性,不然每次递归都要将前面的值清空。
/**
* 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 List<Integer> res = new ArrayList<Integer>();
public List<Integer> preorderTraversal(TreeNode root) {
//特判
if(root == null){
return res;
}
res.add(root.val);
if(root.left != null){
preorderTraversal(root.left);
}
if(root.right != null){
preorderTraversal(root.right);
}
return res;
}
}
leetcode 145 二叉树的后序遍历
/**
* 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 List<Integer> res = new ArrayList<>();
public List<Integer> postorderTraversal(TreeNode root) {
//特判
if(root == null){
return res;
}
if(root.left != null){
postorderTraversal(root.left);
}
if(root.right != null){
postorderTraversal(root.right);
}
res.add(root.val);
return res;
}
}
leetcode 94 二叉树的中序遍历
/**
* 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 List<Integer> res = new ArrayList<>();
public List<Integer> inorderTraversal(TreeNode root) {
//特判
if(root == null){
return res;
}
if(root.left != null){
inorderTraversal(root.left);
}
res.add(root.val);
if(root.right != null){
inorderTraversal(root.right);
}
return res;
}
}
leetcode 102 二叉树的层序遍历
注意先定义两个数组,一个用来记录当前节点的值,一个用来记录当前节点本身。再定义一个size,用来记录当前层的节点的个数,以便区分队列中有哪些节点是属于当前节点的。先考虑while循环条件不满足的情况
/**
* 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 List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> res = new ArrayList<>();
//建立一个队列:用LinkedList<>()实现
Queue<TreeNode> queue = new LinkedList<>();
//特判
if(root == null){
return res;
}
queue.offer(root);
//定义一个size不断记录队列变化的长度
int size = 1;
while(!queue.isEmpty()){
//记录当前层的节点的值
List<Integer> cur = new ArrayList<>();
//记录当前层的节点
List<TreeNode> curNodes = new ArrayList<>();
int j = size;//记录本层最初的size
for(int i = 0; i < j; i++){
TreeNode temp = queue.poll();
curNodes.add(temp);
--size;
cur.add(temp.val);
}
res.add(cur);
for(int i = 0; i < curNodes.size(); i++){
root = curNodes.get(i);
if(root.left != null){
queue.offer(root.left);
++size;
}
if(root.right != null){
queue.offer(root.right);
++size;
}
}
}
return res;
}
}
层序遍历模板:
/**
* 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 List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> res = new ArrayList<>();
//建立一个队列:用LinkedList<>()实现
Queue<TreeNode> queue = new LinkedList<>();
//特判
if(root == null){
return res;
}
queue.offer(root);
while(!queue.isEmpty()){
//记录当前层的节点的值
List<Integer> cur = new ArrayList<>();
//记录当前层节点的个数
int size = queue.size();
while(size != 0){
TreeNode temp = queue.poll();
cur.add(temp.val);
if(temp.left != null){
queue.offer(temp.left);
}
if(temp.right != null){
queue.offer(temp.right);
}
size--;
}
res.add(cur);
}
return res;
}
}
leetcode 226 翻转二叉树
采用前序遍历
/**
* 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 invertTree(TreeNode root) {
//采用前序遍历
if(root == null){return root;}
TreeNode temp;
temp = root.left;
root.left = root.right;
root.right = temp;
invertTree(root.left);
invertTree(root.right);
return root;
}
}
采用中序遍历
/**
* 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 invertTree(TreeNode root) {
//采用中序遍历
if(root == null){return root;}
invertTree(root.left);
TreeNode temp;
temp = root.left;
root.left = root.right;
root.right = temp;
invertTree(root.left);
return root;
}
}
采用后序遍历
/**
* 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 invertTree(TreeNode root) {
//采用后序遍历
if(root == null){return root;}
invertTree(root.left);
invertTree(root.right);
TreeNode temp;
temp = root.left;
root.left = root.right;
root.right = temp;
return root;
}
}
leetcode 101 对称二叉树
首先确定遍历顺序,这一点非常重要。
本题采用后序遍历,因为只有当左右子树都处理完成之后,其得到的结果才可以作为判断对称的条件。
递归三部曲:
1.确定递归函数的参数以及返回值
2.确定递归的终止条件
3.处理单层递归的逻辑
注意:if else语句,代码越往下走,其就被越多的条件过滤过。
/**
* 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 {
//1.确定递归函数的返回值类型和参数
public boolean detectSymmetric(TreeNode left, TreeNode right){
//2.确定递归函数的终止条件
if(left != null && right == null){
return false;
}else if(left == null && right != null){
return false;
}else if(left == null && right == null){
return true;
}else if(left.val != right.val){
return false;
}else{
//3.处理单层递归的逻辑
boolean outside = detectSymmetric(left.left, right.right);
boolean inside = detectSymmetric(left.right, right.left);
return outside && inside;
}
}
public boolean isSymmetric(TreeNode root) {
//采用后序遍历结合递归实现
if(root == null){
return true;
}
return detectSymmetric(root.left, root.right);
}
}
leetcode 104 二叉树的最大深度
注意:求最大深度用前序遍历;求最大高度用后序遍历。
/**
* 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 getMax(int val1, int val2){
return val1 > val2 ? val1 : val2;
}
//采用后序遍历求最大高度,头节点的最大高度就是二叉树的最大深度
public int maxDepth(TreeNode root) {
if(root == null){
return 0;
}
int leftHeight = maxDepth(root.left);
int rightHeight = maxDepth(root.right);
return getMax(leftHeight, rightHeight) + 1;
}
}
leetcode 111 二叉树的最小深度
注意退化成为单链表的二叉树的特殊情况。
/**
* 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 getMin(int val1, int val2){
return val1 < val2 ? val1 : val2;
}
public int getMax(int val1, int val2){
return val1 > val2 ? val1 : val2;
}
public int minDepth(TreeNode root) {
if(root == null){
return 0;
}
int leftHeight = minDepth(root.left);
int rightHeight = minDepth(root.right);
//处理退化成单链表这种特殊情况
if(leftHeight == 0 || rightHeight == 0){
return getMax(leftHeight, rightHeight) + 1;
}
else{
return getMin(leftHeight, rightHeight) + 1;
}
}
}
leetcode 完全二叉树的节点个数
/**
* 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 countNodes(TreeNode root) {
//采用后序遍历
if(root == null){
return 0;
}else{
int leftNodes = countNodes(root.left);
int rightNodes = countNodes(root.right);
return leftNodes + rightNodes + 1;
}
}
}
leetcode 110 判断是否为平衡二叉树
/**
* 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 max(int val1, int val2){
return val1 > val2 ? val1 : val2;
}
public int getHeight(TreeNode root){
if(root == null){
return 0;
}else{
int leftHeight = getHeight(root.left);
int rightHeight = getHeight(root.right);
return max(leftHeight, rightHeight) + 1;
}
}
public boolean isBalanced(TreeNode root) {
//采用后序遍历
if(root == null){
return true;
}else{
int res = getHeight(root.left) > getHeight(root.right) ? getHeight(root.left) - getHeight(root.right) : getHeight(root.right) - getHeight(root.left);
if(res > 1){
return false;
}else{
boolean leftIsBalanced = isBalanced(root.left);
boolean rightIsBalanced = isBalanced(root.right);
return leftIsBalanced && rightIsBalanced;
}
}
}
}
注意:使用前序遍历求二叉树的深度需要用到回溯算法。比如当遍历到某一节点的左子树时,其局部变量depth会加1,当其左子树遍历完成时,若depth不减去1,那么遍历右子树的时候,其计算起始点便和左子树根节点不在同一位置,而是多加了1,所以要回溯减1。每一层递归只关心当前这一层的局部变量。
leetcode 257 二叉树的所有路径
只要有递归就一定有回溯。
注意:引用是地址拷贝。
在写单层递归逻辑的时候需要考虑二叉树的遍历顺序。
leetcode 257 二叉树的所有路径
注意回溯的思想。
int类型转换为字符串类型的几种方法:
1.Integer.toString(int);
2.String.valueOf(int);
3.String var = num + “”;
/**
* 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 List<String> removeLast(List<String> path){
List<String> temp = new ArrayList<>();
for(int i = 0; i < path.size() - 2; i++){
temp.add(path.get(i));
}
return temp;
}
public List<String> res(List<String> path){
List<String> temp = new ArrayList<>();
for(int i = 0; i < path.size() - 1; i++){
temp.add(path.get(i));
}
return temp;
}
public List<String> res = new ArrayList<>();
public List<String> path = new ArrayList<>();
public List<String> binaryTreePaths(TreeNode root) {
//利用前序遍历
if(path.size() != 0 && path.get(path.size() - 1) != "->" ){
path.add("->");
}
path.add(Integer.toString(root.val));
path.add("->");
if(root.left == null && root.right == null){
path = res(path);
String str = "";
for(int i = 0; i < path.size();i++){
str += path.get(i);
}
res.add(str);
return res;
}
if(root.left != null){
binaryTreePaths(root.left);
//回溯
path = removeLast(path);
}
if(root.right != null){
binaryTreePaths(root.right);
//回溯
path = removeLast(path);
}
return res;
}
}
leetcode 404 左叶子之和
注意:左叶子是指是叶子节点且其是父亲的左孩子。
/**
* 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 result = 0;
public int getLeftNodesSum(TreeNode root){
if(root.left == null && root.right == null ){
result += root.val;
return result;
}
if(root.left != null){
result = getLeftNodesSum(root.left);
}
if(root.right != null){
//将右节点赋值为0
root.right.val = 0;
result = getLeftNodesSum(root.right);
}
return result;
}
public int sumOfLeftLeaves(TreeNode root) {
//特判
if(root == null || (root.left == null && root.right == null)){
return 0;
}
return getLeftNodesSum(root);
}
}
leetcode 513 找树左下角的值
本题同样利用回溯的思想。
/**
* 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 {
//定义全局变量。就算递归遍历到最后一层的右节点,也不会修改res,因为其所在层数与最后一层的左节点相同
public int maxDepth = 0;
public int res;
//定义递归函数,通过递归函数来修改全局变量的值
public void getValue(TreeNode root, int depth){
//定义递归终止的条件
if(root.left == null && root.right == null){
if(depth > maxDepth){
maxDepth = depth;
res = root.val;
}
}
//定义单层递归的逻辑
if(root.left != null){
//回溯
depth++;
getValue(root.left, depth);
depth--;
}
if(root.right != null){
//回溯
depth++;
getValue(root.right, depth);
depth--;
}
}
public int findBottomLeftValue(TreeNode root) {
getValue(root, 1);
return res;
}
}
leetcode 112 路径总和
本题依旧利用回溯的思想
/**
* 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 res = false;
public int target;
public void findPath(TreeNode root,int sum){
if(root.left == null && root.right == null){
sum += root.val;
if(sum == target){
res = true;}
}
if(root.left != null){
sum += root.val;
findPath(root.left, sum);
sum -= root.val;
}
if(root.right != null){
sum += root.val;
findPath(root.right, sum);
sum -= root.val;
}
}
public boolean hasPathSum(TreeNode root, int targetSum) {
//特判
if(root == null){
return res;
}
target = targetSum;
findPath(root,0);
return res;
}
}
leetcode 106 从中序与后序遍历序列构造二叉树
分为6步:
1.后序数组为0,表示为空节点
2.后序数组最后一个元素为节点元素
3.寻找中序数组位置作为切割点
4.切中序数组
5.切后序数组(用中序数组的左区间的大小来切后序数组,同样得到后序数组中左区间的节点,剩下的便是后序数组中右区间的大小)
6.递归处理左区间和右区间(root.left(左中序,左后序);root.right(右中序,右后序))
区间遵循左闭右开的原则。前序和后序不能还原一颗二叉树,因为左右区间的的界限无法确定。
注意:递归函数本身无返回值,则定义全局变量,利用递归函数改变全局变量的值。
递归函数有返回值,定义递归函数的局部变量,每进入一层递归都将局部变量初始化一次,所以要注意传递需要保留其累加值的局部变量。
注意:确定后序中右子树所对应的区间比较考察细节。
/**
* 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 buildTree(int[] inorder, int[] postorder) {
//定义递归的终止条件
if(postorder.length == 0){
return null;
}
//定义该树的根节点
TreeNode node = new TreeNode(postorder[postorder.length - 1]);
//该树只有一个节点
if(postorder.length == 1){
return node;
}
//定义单层递归逻辑
int k = postorder[postorder.length - 1];
int index = 0;//index表示中序的切割位置
for(int i = 0; i < inorder.length; i++){
if(inorder[i] == k){
index = i;
break;
}
}
//切中序
//定义左子树区间
List<Integer> leftIn = new ArrayList<>();
for(int i = 0; i <= index - 1; i++){
leftIn.add(inorder[i]);
}
//定义右子树区间
List<Integer> rightIn = new ArrayList<>();
for(int i = index + 1; i < inorder.length; i++){
rightIn.add(inorder[i]);
}
//计算后序里的左子树区间:后序的左子树区间一定与中序的左子树区间相同
List<Integer> leftPos = new ArrayList<>();
for(int i = 0; i < leftIn.size(); i++){
leftPos.add(postorder[i]);
}
//计算后序里的右子树区间
List<Integer> rightPos = new ArrayList<>();
int temp = postorder.length - 1 - leftPos.size();
int j = leftPos.size();
while(temp != 0){
rightPos.add(postorder[j]);
j += 1;
temp--;
}
//递归构造左子树
//定义toArray工具方法
int[] leftInArray = new int[leftIn.size()];
for(int i = 0; i < leftIn.size(); i++){
leftInArray[i] = leftIn.get(i);
}
int[] leftPosArray = new int[leftPos.size()];
for(int i = 0; i < leftPos.size(); i++){
leftPosArray[i] = leftPos.get(i);
}
node.left = buildTree(leftInArray, leftPosArray);
//递归构造右子树
int[] rightInArray = new int[rightIn.size()];
for(int i = 0; i < rightIn.size(); i++){
rightInArray[i] = rightIn.get(i);
}
int[] rightPosArray = new int[rightPos.size()];
for(int i = 0; i < rightPos.size(); i++){
rightPosArray[i] = rightPos.get(i);
}
node.right = buildTree(rightInArray, rightPosArray);
return node;
}
}
leetcode 654 最大二叉树
本题递归的终止条件是nums数组只有一个元素。
/**
* 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;
}
int max = nums[0];
//记录最大元素的下标
int flag = 0;
for(int i = 1; i < nums.length; i++){
if(nums[i] > max){
max = nums[i];
flag = i;
}
}
TreeNode node = new TreeNode(max);
//递归的终止条件
if(nums.length == 1){
TreeNode temp = new TreeNode(nums[0]);
return temp;
}
//单层递归逻辑
//左子树
int[] left = new int[flag];
for(int i = 0; i < flag; i++){
left[i] = nums[i];
}
//右子树
int[] right = new int[nums.length - 1 - left.length];
int j = flag + 1;//右子树的起始节点的下标
for(int i = 0; i < right.length; i++){
right[i] = nums[j];
j++;
}
node.left = constructMaximumBinaryTree(left);
node.right = constructMaximumBinaryTree(right);
return node;
}
}
leetcode 617 合并二叉树
本题用前序遍历。tree1与tree2同步进行遍历。
/**
* 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;
}
//单层递归逻辑
TreeNode node = new TreeNode(root1.val + root2.val);
node.left = mergeTrees(root1.left, root2.left);
node.right = mergeTrees(root1.right, root2.right);
return node;
}
}
leetcode 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.left == null && root.right == null && root.val != val){
return null;
}
//单层递归逻辑
TreeNode res = root;//指向root的指针res
if(val < root.val){
res = searchBST(root.left, val);
}
if(val > root.val){
res = searchBST(root.right, val);
}
if(val == root.val){
return root;
}
return res;
}
}
leetcode 98 验证二叉搜索树
二叉搜索树的中序遍历是升序排列的。
解法一:采用中序遍历
/**
* 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 List<Integer> res = new ArrayList<>();
public void inorder(TreeNode root){
if(root.left != null){
inorder(root.left);
}
res.add(root.val);
if(root.right != null){
inorder(root.right);
}
}
public boolean isValidBST(TreeNode root) {
if(root == null){
return false;
}
if(root.left == null && root.right == null){
return true;
}
//中序遍历该树
inorder(root);
int[] nums = new int[res.size()];
for(int i = 0; i < res.size();i++){
nums[i] = this.res.get(i);
}
//判断nums数组是否是升序的
int temp = nums.length - 1;
int j = 0;
while(temp != 0){
if(nums[j] < nums[j+1]){
--temp;
++j;
continue;
}
break;
}
if(temp != 0){
return false;
}else{
return true;
}
}
}
解法二:
利用双指针的思想。
/**
* 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 pre = null;
public boolean isValidBST(TreeNode root) {
if(root == null){
return true;
}
//采用中序遍历
boolean left = isValidBST(root.left);
if(pre != null && pre.val >= root.val){
return false;
}
pre = root;
boolean right = isValidBST(root.right);
return left && right;
}
}
leetcode 530 二叉搜索树的最小绝对差
注意:因为和BST相关,所以优先考虑中序遍历。
本题利用双指针的方法,递归函数的返回值为void,传入的参数为当前节点cur。pre为当前节点的前一个中序遍历节点,初始为null。节点的移动用pre = cur实现。
/**
* 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 min = Integer.MAX_VALUE;
public int min(int val1, int val2){
return val1 < val2 ? val1 : val2;
}
public TreeNode pre = null;
public void getMinimumDifferenceHelper(TreeNode cur){
if(cur == null){
return;
}
getMinimumDifferenceHelper(cur.left);
if(pre != null){
min = min(cur.val < pre.val ? pre.val - cur.val : cur.val - pre.val, min);
}
pre = cur;
getMinimumDifferenceHelper(cur.right);
}
public int getMinimumDifference(TreeNode root) {
getMinimumDifferenceHelper(root);
return min;
}
}
leetcode 501 二叉搜索树中的众数
解法一:(复杂版,不推荐)
需要用到双指针,优先队列,HashMap的遍历。
/**
* 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 pre = null;
public int count = 1;
public HashMap<Integer, Integer> map = new HashMap<>();
public PriorityQueue<Integer> pq = new PriorityQueue<>(new Comparator<Integer>()
{
@Override
public int compare(Integer o1, Integer o2) {
return o2-o1; //大根堆
}
}
);
public List<Integer> res = new ArrayList<>();
public void findModeHelper(TreeNode cur){
if(cur == null){
return;
}
//采用中序遍历
findModeHelper(cur.left);
if(pre != null){
if(cur.val == pre.val){
count++;
map.put(pre.val, count);
}
if(cur.val != pre.val){
map.put(cur.val, count);
count = 1;
}
}
map.put(cur.val, count);
pre = cur;
findModeHelper(cur.right);
}
public int[] findMode(TreeNode root) {
if(root.left == null && root.right == null){
int[] res2 = new int[1];
res2[0] = root.val;
return res2;
}
findModeHelper(root);
for(Integer value : map.values()){
pq.add(value);
}
//value -> key
int temp = pq.poll();
for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
if (Objects.equals(entry.getValue(), temp)) {
res.add(entry.getKey());
}
}
// int[] result = res.toArray(new int[res.size()]);
int[] result = new int[res.size()];
for(int i = 0; i < res.size(); i++){
result[i] = res.get(i);
}
return result;
}
}