1 二叉树的遍历
1.1 前序遍历
- 递归
// 144. 二叉树的前序遍历
// 给你二叉树的根节点 root ,返回它节点值的 前序 遍历。
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<>();
preOrder(root,res);
return res;
}
private void preOrder(TreeNode root,List<Integer> res) {
if (root == null) return;
res.add(root.val);
preOrder(root.left,res);
preOrder(root.right,res);
}
}
- 迭代
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<>();
if (root == null) return res;
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
while (!stack.isEmpty()) {
TreeNode tmpNode = stack.pop();
res.add(tmpNode.val);
if (tmpNode.right != null) stack.push(tmpNode.right);
if (tmpNode.left != null) stack.push(tmpNode.left);
}
return res;
}
}
1.2 中序遍历
- 递归
// 94. 二叉树的中序遍历
// 给定一个二叉树的根节点 root ,返回它的 中序 遍历。
class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<>();
inOrder(root,res);
return res;
}
private void inOrder(TreeNode root,List<Integer> res) {
if (root == null) return;
inOrder(root.left,res);
res.add(root.val);
inOrder(root.right,res);
}
}
- 迭代
class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<>();
if (root == null) return res;
Stack<TreeNode> stack = new Stack<>();
TreeNode cur = root;
while (cur != null || !stack.isEmpty()) {
if (cur != null) {
stack.push(cur);
cur = cur.left;
} else {
cur = stack.pop();
res.add(cur.val);
cur = cur.right;
}
}
return res;
}
}
1.3 后序遍历
- 递归
// 145. 二叉树的后序遍历
// 给定一个二叉树,返回它的 后序 遍历。
class Solution {
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<>();
postOrder(root,res);
return res;
}
private void postOrder(TreeNode root,List<Integer> res) {
if (root == null) return;
postOrder(root.left,res);
postOrder(root.right,res);
res.add(root.val);
}
}
- 迭代
class Solution {
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<>();
if (root == null) return res;
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
while (!stack.isEmpty()) {
TreeNode tmpNode = stack.pop();
res.add(tmpNode.val);
if (tmpNode.left != null) stack.push(tmpNode.left);
if (tmpNode.right != null) stack.push(tmpNode.right);
}
Collections.reverse(res);
return res;
}
}
1.4 层序遍历
// 102. 二叉树的层序遍历
// 给你一个二叉树,请你返回其按 层序遍历 得到的节点值。 (即逐层地,从左到右访问所有节点)。
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> res = new ArrayList<>();
if (root == null) return res;
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()) {
int len = queue.size();
List<Integer> tmpList = new ArrayList<>();
for (int i = 0; i < len; i++) {
TreeNode tmpNode = queue.poll();
tmpList.add(tmpNode.val);
if (tmpNode.left != null) queue.offer(tmpNode.left);
if (tmpNode.right != null) queue.offer(tmpNode.right);
}
res.add(tmpList);
}
return res;
}
}
2 二叉树的属性
思路:
- 如果需要搜索整颗二叉树且不用处理递归返回值,递归函数就不要返回值。113
- 如果需要搜索整颗二叉树且需要处理递归返回值,递归函数就需要返回值。 236
- 如果要搜索其中一条符合条件的路径,那么递归一定需要返回值,因为遇到符合条件的路径了就要及时返回。112
// DFS 后序遍历
// 101. 对称二叉树
// 给定一个二叉树,检查它是否是镜像对称的。
class Solution {
public boolean isSymmetric(TreeNode root) {
return compare(root.left,root.right);
}
private boolean compare (TreeNode left, TreeNode right) {
if (left == null && right != null) return false;
if (left != null && right == null) return false;
if (left == null && right == null) return true;
if (left.val != right.val) return false;
boolean outFlag = compare(left.left,right.right);
boolean inFlag = compare(left.right,right.left);
return outFlag && inFlag;
}
}
// DFS 后序遍历
// 104. 二叉树的最大深度
// 给定一个二叉树,找出其最大深度。二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。
class Solution {
public int maxDepth(TreeNode root) {
return getDepth(root);
}
private int getDepth(TreeNode root) {
if (root == null) return 0;
int leftDepth = getDepth(root.left);
int rightDepth = getDepth(root.right);
return 1 + Math.max(leftDepth,rightDepth);
}
}
// DFS 后序遍历
// 559. N 叉树的最大深度
// 给定一个 N 叉树,找到其最大深度。最大深度是指从根节点到最远叶子节点的最长路径上的节点总数。N 叉树输入按层序遍历序列化表示,每组子节点由空值分隔(请参见示例)。
class Solution {
public int maxDepth(Node root) {
if (root == null) return 0;
int maxDepth = 0;
for (int i = 0 ; i < root.children.size(); i++) {
int deep = maxDepth(root.children.get(i));
maxDepth = Math.max(maxDepth,deep);
}
return 1 + maxDepth;
}
}
// DFS 后序遍历
// 111. 二叉树的最小深度
// 给定一个二叉树,找出其最小深度。最小深度是从根节点到最近叶子节点的最短路径上的节点数量。
class Solution {
public int minDepth(TreeNode root) {
return getDepth(root);
}
private int getDepth(TreeNode root) {
if (root == null) return 0;
int leftDepth = getDepth(root.left);
int rightDepth = getDepth(root.right);
if (root.left == null && root.right != null) {
return 1 + rightDepth;
} else if (root.left != null && root.right == null) {
return 1 + leftDepth;
} else {
return 1 + Math.min(leftDepth,rightDepth);
}
}
}
// DFS 后序遍历
// 222. 完全二叉树的节点个数
// 给你一棵 完全二叉树 的根节点 root ,求出该树的节点个数。完全二叉树 的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层,则该层包含 1~ 2h 个节点。
class Solution {
public int countNodes(TreeNode root) {
if (root == null) return 0;
int leftNum = countNodes(root.left);
int rightNum = countNodes(root.right);
return 1 + leftNum + rightNum;
}
}
// DFS 后序遍历
// 110. 平衡二叉树
// 给定一个二叉树,判断它是否是高度平衡的二叉树。本题中,一棵高度平衡二叉树定义为:一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1 。
class Solution {
public boolean isBalanced(TreeNode root) {
return getHeight(root) == -1 ? false : true;
}
private int getHeight(TreeNode root) {
if (root == null) return 0;
int leftHeight = getHeight(root.left);
if (leftHeight == -1) {
return -1;
}
int rightHeight = getHeight(root.right);
if (rightHeight == -1) {
return -1;
}
return Math.abs(leftHeight - rightHeight) > 1 ? -1 : 1 + Math.max(leftHeight,rightHeight);
}
}
// DFS 前序遍历
// 257. 二叉树的所有路径
// 给你一个二叉树的根节点 root ,按 任意顺序 ,返回所有从根节点到叶子节点的路径。
class Solution {
public List<String> binaryTreePaths(TreeNode root) {
List<String> res = new ArrayList<>();
if (root == null) return res;
List<Integer> paths = new ArrayList<>();
traversal(root,paths,res);
return res;
}
private void traversal(TreeNode root,List<Integer> paths,List<String> res) {
paths.add(root.val);
if (root.left == null && root.right == null) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < paths.size() - 1; i++) {
sb.append(paths.get(i) + "->");
}
sb.append(paths.get(paths.size() - 1));
res.add(sb.toString());
return;
}
if (root.left != null) {
traversal(root.left,paths,res);
paths.remove(paths.size() - 1);
}
if (root.right != null) {
traversal(root.right,paths,res);
paths.remove(paths.size() - 1);
}
}
}
// DFS 后序遍历
// 404. 左叶子之和
// 计算给定二叉树的所有左叶子之和。
class Solution {
public int sumOfLeftLeaves(TreeNode root) {
if (root == null) return 0;
int leftValue = sumOfLeftLeaves(root.left);
int rightValue = sumOfLeftLeaves(root.right);
int midValue = 0;
if (root.left != null && root.left.left == null && root.left.right == null) {
midValue = root.left.val;
}
return leftValue + rightValue + midValue;
}
}
// DFS 前序遍历
// 513. 找树左下角的值
// 给定一个二叉树的 根节点 root,请找出该二叉树的 最底层 最左边 节点的值。假设二叉树中至少有一个节点。
class Solution {
private int maxDeep;
private int maxVal;
public int findBottomLeftValue(TreeNode root) {
maxVal = root.val;
maxDeep = 0;
travesal(root,0);
return maxVal;
}
private void travesal(TreeNode root,int tmpDeep) {
if (root == null) return;
if (root.left == null && root.right == null) {
if (tmpDeep > maxDeep) {
maxDeep = tmpDeep;
maxVal = root.val;
}
}
travesal(root.left,tmpDeep + 1); //隐式回溯
travesal(root.right,tmpDeep + 1);
}
}
// DFS 前序遍历(中节点没有逻辑)
// 112. 路径总和
// 给你二叉树的根节点 root 和一个表示目标和的整数 targetSum ,判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 targetSum 。
class Solution {
public boolean hasPathSum(TreeNode root, int targetSum) {
if (root == null) return false;
return traversal(root,targetSum - root.val);
}
private boolean traversal(TreeNode root, int tmpSum) {
if (root.left == null && root.right == null && tmpSum == 0) return true;
if (root.left == null && root.right == null) return false;
if (root.left != null) {
if (traversal(root.left,tmpSum - root.left.val)) return true;
}
if (root.right != null) {
if (traversal(root.right,tmpSum - root.right.val)) return true;
}
return false;
}
}
// DFS 前序遍历
// 113. 路径总和 II
// 给你二叉树的根节点 root 和一个整数目标和 targetSum ,找出所有 从根节点到叶子节点 路径总和等于给定目标和的路径。
class Solution {
private List<List<Integer>> res = new ArrayList<>();
private List<Integer> path = new ArrayList<>();
public List<List<Integer>> pathSum(TreeNode root, int targetSum) {
if (root == null) return res;
path.add(root.val);
traversal(root,targetSum - root.val);
return res;
}
private void traversal(TreeNode root, int tmpNum) {
if (root.left == null && root.right == null && tmpNum == 0) {
res.add(new ArrayList<>(path));
return;
}
if (root.left == null && root.right == null) return;
if (root.left != null) {
path.add(root.left.val);
tmpNum -= root.left.val;
traversal(root.left,tmpNum);
tmpNum += root.left.val;
path.remove(path.size() - 1);
}
if (root.right != null) {
path.add(root.right.val);
tmpNum -= root.right.val;
traversal(root.right,tmpNum);
tmpNum += root.right.val;
path.remove(path.size() - 1);
}
}
}
3 二叉树的修改与构造
// DFS 前序遍历
// 226. 翻转二叉树
// 翻转一棵二叉树。
class Solution {
public TreeNode invertTree(TreeNode root) {
if (root == null) return root;
swap(root);
invertTree(root.left);
invertTree(root.right);
return root;
}
private void swap(TreeNode root) {
TreeNode tmpNode = root.left;
root.left = root.right;
root.right = tmpNode;
}
}
// 106. 从中序与后序遍历序列构造二叉树
// 根据一棵树的中序遍历与后序遍历构造二叉树。
class Solution {
public TreeNode buildTree(int[] inorder, int[] postorder) {
return buildTree(inorder,0,inorder.length,postorder,0,postorder.length);
}
private TreeNode buildTree(int[] inorder,int inLeft,int inRight,int[] postorder,int postLeft,int postRight) {
if (inRight - inLeft < 1) return null;
int rootVal = postorder[postRight - 1];
TreeNode root = new TreeNode(rootVal);
int rootIndex = 0;
for (int i = inLeft; i < inRight; i++) {
if (inorder[i] == rootVal) {
rootIndex = i;
break;
}
}
// 根据rootIndex划分左右子树
root.left = buildTree(inorder,inLeft,rootIndex,postorder,postLeft,postLeft + (rootIndex - inLeft));
root.right = buildTree(inorder,rootIndex + 1,inRight,postorder,postLeft + (rootIndex - inLeft),postRight - 1);
return root;
}
}
// DFS 前序遍历
// 105. 从前序与中序遍历序列构造二叉树
// 给定一棵树的前序遍历 preorder 与中序遍历 inorder。请构造二叉树并返回其根节点。
class Solution {
public TreeNode buildTree(int[] preorder, int[] inorder) {
return buildTree(preorder,0,preorder.length,inorder,0,inorder.length);
}
private TreeNode buildTree(int[] preorder,int preLeft,int preRight,int[] inorder,int inLeft,int inRight) {
if (inRight - inLeft < 1) return null;
int rootVal = preorder[preLeft];
TreeNode root = new TreeNode(rootVal);
int rootIndex = 0;
for (int i = inLeft; i < inRight; i++) {
if (inorder[i] == rootVal) {
rootIndex = i;
break;
}
}
root.left = buildTree(preorder,preLeft + 1,preLeft + 1 + (rootIndex - inLeft),inorder,inLeft,rootIndex);
root.right = buildTree(preorder,preLeft + 1 + (rootIndex - inLeft),preRight,inorder,rootIndex + 1,inRight);
return root;
}
}
// DFS 前序遍历
// 654. 最大二叉树
// 给定一个不含重复元素的整数数组 nums 。一个以此数组直接递归构建的 最大二叉树 定义如下:二叉树的根是数组 nums 中的最大元素。左子树是通过数组中 最大值左边部分 递归构造出的最大二叉树。右子树是通过数组中 最大值右边部分 递归构造出的最大二叉树。返回有给定数组 nums 构建的 最大二叉树 。
class Solution {
public TreeNode constructMaximumBinaryTree(int[] nums) {
return constructMaximumBinaryTree(nums,0,nums.length);
}
private TreeNode constructMaximumBinaryTree(int[] nums,int preLeft,int preRight) {
if (preRight - preLeft < 1) return null;
// 初始赋值
int maxValue = nums[preLeft];
int maxIndex = preLeft;
for (int i = preLeft + 1; i < preRight; i++) {
if (nums[i] > maxValue) {
maxValue = nums[i];
maxIndex = i;
}
}
TreeNode root = new TreeNode(maxValue);
root.left = constructMaximumBinaryTree(nums,preLeft,maxIndex);
root.right = constructMaximumBinaryTree(nums,maxIndex + 1,preRight);
return root;
}
}
// DFS 前序遍历
// 617. 合并二叉树
// 给定两个二叉树,想象当你将它们中的一个覆盖到另一个上时,两个二叉树的一些节点便会重叠。你需要将他们合并为一个新的二叉树。合并的规则是如果两个节点重叠,那么将他们的值相加作为节点合并后的新值,否则不为 NULL 的节点将直接作为新二叉树的节点。
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;
}
}
4 二叉搜索树
思路:
- 二叉搜索树是一个有序树:
- 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
- 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
- 它的左、右子树也分别为二叉搜索树
- 中序遍历下,输出的二叉搜索树节点的数值是有序序列。
// DFS 搜索遍历 找到结果直接return
// 700. 二叉搜索树中的搜索
// 给定二叉搜索树(BST)的根节点和一个值。 你需要在BST中找到节点值等于给定值的节点。 返回以该节点为根的子树。 如果节点不存在,则返回 NULL。
class Solution {
public TreeNode searchBST(TreeNode root, int val) {
if (root == null || root.val == val) return root;
if (root.val > val) return searchBST(root.left,val);
if (root.val < val) return searchBST(root.right,val);
return null;
}
}
// DFS 中序遍历 找到结果直接return
// 98. 验证二叉搜索树
// 给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。有效 二叉搜索树定义如下:节点的左子树只包含 小于 当前节点的数。节点的右子树只包含 大于 当前节点的数。所有左子树和右子树自身必须也是二叉搜索树。
class Solution {
private long pre = Long.MIN_VALUE;
public boolean isValidBST(TreeNode root) {
if (root == null) return true;
if (!isValidBST(root.left)) return false;
if (root.val <= pre) return false;
pre = root.val;
return isValidBST(root.right);
}
}
// DFS 中序遍历
// 530. 二叉搜索树的最小绝对差
// 给你一个二叉搜索树的根节点 root ,返回 树中任意两不同节点值之间的最小差值 。差值是一个正数,其数值等于两值之差的绝对值。
class Solution {
private TreeNode pre;
private int diff = Integer.MAX_VALUE;
public int getMinimumDifference(TreeNode root) {
if (root == null) return 0;
traversal(root);
return diff;
}
private void traversal(TreeNode root) {
if (root == null) return;
traversal(root.left);
if (pre != null) {
diff = Math.min(diff,root.val - pre.val);
}
pre = root;
traversal(root.right);
}
}
// DFS 中序遍历
// 501. 二叉搜索树中的众数
// 给定一个有相同值的二叉搜索树(BST),找出 BST 中的所有众数(出现频率最高的元素)。
class Solution {
private List<Integer> resList = new ArrayList<>();
private TreeNode pre;
private int maxCount = 0;
private int count = 0;
public int[] findMode(TreeNode root) {
traversal(root);
int[] res = new int[resList.size()];
for (int i = 0; i < res.length; i++) {
res[i] = resList.get(i);
}
return res;
}
private void traversal(TreeNode root) {
if (root == null) return;
traversal(root.left);
if (pre == null || root.val != pre.val) {
count = 1;
} else {
count++;
}
if (count > maxCount) {
maxCount = count;
resList.clear();
resList.add(root.val);
} else if (count == maxCount) {
resList.add(root.val);
}
pre = root;
traversal(root.right);
}
}
// DFS 中序遍历变种
// 538. 把二叉搜索树转换为累加树
// 给出二叉 搜索 树的根节点,该树的节点值各不相同,请你将其转换为累加树(Greater Sum Tree),使每个节点 node 的新值等于原树中大于或等于 node.val 的值之和。
class Solution {
private int sum = 0;
public TreeNode convertBST(TreeNode root) {
traversal(root);
return root;
}
private void traversal(TreeNode root) {
if (root == null) return;
traversal(root.right);
sum += root.val;
root.val = sum;
traversal(root.left);
}
}
5 二叉树的公共祖先问题
思路 :
- 求最小公共祖先,需要从底向上遍历,那么二叉树,只能通过后序遍历(即:回溯)实现从低向上的遍历方式。
- 在回溯的过程中,必然要遍历整颗二叉树,即使已经找到结果了,依然要把其他节点遍历完,因为要使用递归函数的返回值(也就是代码中的left和right)做逻辑判断。
// DFS 后序遍历
// 本题函数有返回值,是因为回溯的过程需要递归函数的返回值做判断,但本题我们依然要遍历树的所有节点。递归函数有返回值就是要遍历某一条边,但有返回值也要看如何处理返回值。如果递归函数有返回值,如何区分要搜索一条边,还是搜索整个树呢?
// 搜索一条边的写法:
// if (递归函数(root->left)) return ;
// if (递归函数(root->right)) return ;
// 搜索整个树写法:
// left = 递归函数(root->left);
// right = 递归函数(root->right);
// left与right的逻辑处理;
// 在递归函数有返回值的情况下:如果要搜索一条边,递归函数返回值不为空的时候,立刻返回,如果搜索整个树,直接用一个变量left、right接住返回值,这个left、right后序还有逻辑处理的需要,也就是后序遍历中处理中间节点的逻辑(也是回溯)。
// 236. 二叉树的最近公共祖先
// 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
return traversal(root,p,q);
}
private TreeNode traversal(TreeNode root,TreeNode p,TreeNode q) {
if (root == p || root == q || root == null) return root;
TreeNode leftNode = traversal(root.left,p,q);
TreeNode rightNode = traversal(root.right,p,q);
if (leftNode != null && rightNode != null) {
return root;
} else if (leftNode == null && rightNode != null) {
return rightNode;
} else if (leftNode != null && rightNode == null) {
return leftNode;
} else {
return null;
}
}
}
// DFS 前序遍历(节点无处理逻辑)
// 和二叉树:公共祖先问题不同,普通二叉树求最近公共祖先需要使用回溯,从底向上来查找,二叉搜索树就不用了,因为搜索树有序(相当于自带方向),那么只要从上向下遍历就可以了。
// 235. 二叉搜索树的最近公共祖先
// 给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
return traversal(root,p,q);
}
private TreeNode traversal(TreeNode root,TreeNode p,TreeNode q) {
if (root == null) return null;
if (root.val > p.val && root.val > q.val) {
TreeNode leftNode = traversal(root.left,p,q);
if (leftNode != null) return leftNode;
}
if (root.val < p.val && root.val < q.val) {
TreeNode rightNode = traversal(root.right,p,q);
if (rightNode != null) return rightNode;
}
return root;
}
}
6 二叉搜索树的修改与构造
// DFS 搜索遍历
// 有返回值的话,可以利用返回值完成新加入的节点与其父节点的赋值操作
// 701. 二叉搜索树中的插入操作
// 给定二叉搜索树(BST)的根节点和要插入树中的值,将值插入二叉搜索树。 返回插入后二叉搜索树的根节点。 输入数据 保证 ,新值和原始二叉搜索树中的任意节点值都不同。
class Solution {
public TreeNode insertIntoBST(TreeNode root, int val) {
if (root == null) {
TreeNode node = new TreeNode(val);
return node;
}
if (root.val > val) root.left = insertIntoBST(root.left,val);
if (root.val < val) root.right = insertIntoBST(root.right,val);
return root;
}
}
// DFS 搜索遍历
// 有以下五种情况:
// 第一种情况:
// 没找到删除的节点,遍历到空节点直接返回了
// 找到删除的节点:
// 第二种情况:左右孩子都为空(叶子节点),直接删除节点, 返回NULL为根节点
// 第三种情况:删除节点的左孩子为空,右孩子不为空,删除节点,右孩子补位,返回右孩子为根节点
// 第四种情况:删除节点的右孩子为空,左孩子不为空,删除节点,左孩子补位,返回左孩子为根节点
// 第五种情况:左右孩子节点都不为空,则将删除节点的左子树头结点(左孩子)放到删除节点的右子树的最左面节点的左孩子上,返回删除节点右孩子为新的根节点。
// 450. 删除二叉搜索树中的节点
// 给定一个二叉搜索树的根节点 root 和一个值 key,删除二叉搜索树中的 key 对应的节点,并保证二叉搜索树的性质不变。返回二叉搜索树(有可能被更新)的根节点的引用。
class Solution {
public TreeNode deleteNode(TreeNode root, int key) {
if (root == null) return null;
if (root.val == key) {
if (root.left == null && root.right == null) {
return null;
} else if (root.left != null && root.right == null) {
return root.left;
} else if (root.left == null && root.right != null) {
return root.right;
} else {
TreeNode cur = root.right;
while (cur.left != null) {
cur = cur.left;
}
cur.left = root.left;
return root.right;
}
}
if (root.val > key) root.left = deleteNode(root.left,key);
if (root.val < key) root.right = deleteNode(root.right,key);
return root;
}
}
// DFS 搜索遍历
// 因为是要遍历整棵树,做修改,其实不需要返回值也可以,我们也可以完成修剪(其实就是从二叉树中移除节点)的操作。但是有返回值,更方便,可以通过递归函数的返回值来移除节点。
// 669. 修剪二叉搜索树
// 给你二叉搜索树的根节点 root ,同时给定最小边界low 和最大边界 high。通过修剪二叉搜索树,使得所有节点的值在[low, high]中。修剪树不应该改变保留在树中的元素的相对结构(即,如果没有被移除,原有的父代子代关系都应当保留)。 可以证明,存在唯一的答案。
class Solution {
public TreeNode trimBST(TreeNode root, int low, int high) {
if (root == null) return null;
if (root.val < low) {
TreeNode rightNode = trimBST(root.right,low,high);
return rightNode;
}
if (root.val > high) {
TreeNode leftNode = trimBST(root.left,low,high);
return leftNode;
}
root.left = trimBST(root.left,low,high);
root.right = trimBST(root.right,low,high);
return root;
}
}
// DFS 前序遍历
// 108. 将有序数组转换为二叉搜索树
// 给你一个整数数组 nums ,其中元素已经按 升序 排列,请你将其转换为一棵 高度平衡 二叉搜索树。
class Solution {
public TreeNode sortedArrayToBST(int[] nums) {
return traversal(nums,0,nums.length - 1); // [left,right]
}
private TreeNode traversal(int[] nums,int left,int right) {
if (left > right) return null;
int mid = left + ((right - left) >> 1);
TreeNode root = new TreeNode(nums[mid]);
root.left = traversal(nums,left,mid - 1);
root.right = traversal(nums,mid + 1,right);
return root;
}
}