231011刷题记录
参考代码代码随想录来刷的
关键词:二叉树、修剪二叉搜索树
1 669. 修剪二叉搜索树
力扣题目链接
给你二叉搜索树的根节点 root ,同时给定最小边界low 和最大边界 high。通过修剪二叉搜索树,使得所有节点的值在[low, high]中。修剪树 不应该 改变保留在树中的元素的相对结构 (即,如果没有被移除,原有的父代子代关系都应当保留)。 可以证明,存在 唯一的答案 。
所以结果应当返回修剪好的二叉搜索树的新的根节点。注意,根节点可能会根据给定的边界发生改变。
解法一
昨天做过一道题,删除二叉搜索树中的节点。
可采用这个思路来做,遍历所有结点,如果结点没在范围内,即要删除该结点。
缺点是要遍历所有结点。
理论上来说,假如某个结点的值小于low,那么该结点的左子树必定全都小于low,那么不用遍历该节点的左子树了。
class Solution {
public TreeNode trimBST(TreeNode root, int low, int high) {
if (root == null)
return null;
root.left = trimBST(root.left, low, high);
root.right = trimBST(root.right, low, high);
if (root.val < low || root.val > high) {
if (root.left == null && root.right == null)
return null;
else if (root.left == null)
return root.right;
else if (root.right == null)
return root.left;
else if (root.val > high)
return root.left;
else
return root.right;
}
return root;
}
}
解法二
递归
class Solution {
public TreeNode trimBST(TreeNode root, int low, int high) {
if (root == null)
return null;
if (root.val < low)
return trimBST(root.right, low, high);
if (root.val > high)
return trimBST(root.left, low, high);
root.left = trimBST(root.left, low, high);
root.right = trimBST(root.right, low, high);
return root;
}
}
解法三
迭代
- 先处理好根节点,是根节点的值在范围内。
- 处理左子树,左子树的所有结点值必定小于high,只用判定左子树的结点值是否小于low。
如果小于low,就让根结点的左子树等于左子树的右子树,知道左子树为null或者左子树的结点值大于等于low为止。
大于等于low不用做处理。
让cur更新为cur.left,继续处理。 - 处理右子树。
class Solution {
public TreeNode trimBST(TreeNode root, int low, int high) {
if (root == null)
return null;
// 1 处理根结点
while (root != null && (root.val < low || root.val > high))
if (root.val < low)
root = root.right;
else
root = root.left;
// 2 处理左子树
TreeNode cur = root;
while (cur != null) {
while (cur.left != null && cur.left.val < low) {
cur.left = cur.left.right;
}
// 为什么此处只处理左子树,不处理右子树?
// 因为上面那个循环结束,表明
// - cur.left为null
// - 或者cur.left.val大于low,并且cur.left的右子树必定大于low,小于high
// 因为cur小于high、cur.left的右子树小于cur,故cur.left的右子树小于high
cur = cur.left;
}
// 3 处理右子树
cur = root;
while (cur != null) {
while (cur.right != null && cur.right.val > high) {
cur.right = cur.right.left;
}
cur = cur.right;
}
return root;
}
}
2 108.将有序数组转换为二叉搜索树
力扣题目链接
给你一个整数数组 nums ,其中元素已经按 升序 排列,请你将其转换为一棵 高度平衡 二叉搜索树。
高度平衡 二叉树是一棵满足「每个节点的左右两个子树的高度差的绝对值不超过 1 」的二叉树。
之前做过类似的,用数组构造二叉树。
此题要平衡,那么取数组中间位置的数为根结点即可。
class Solution {
public TreeNode sortedArrayToBST(int[] nums) {
return build(nums, 0, nums.length);
}
// 左闭右开
private TreeNode build(int[] nums, int begin, int end) {
if (begin >= end)
return null;
int mid = (end + begin) / 2;
TreeNode root = new TreeNode(nums[mid]);
root.left = build(nums, begin, mid);
root.right = build(nums, mid + 1, end);
return root;
}
}
3 538.把二叉搜索树转换为累加树
力扣题目链接
给出二叉 搜索 树的根节点,该树的节点值各不相同,请你将其转换为累加树(Greater Sum Tree),使每个节点 node 的新值等于原树中大于或等于 node.val 的值之和。
提醒一下,二叉搜索树满足下列约束条件:
- 节点的左子树仅包含键 小于 节点键的节点。
- 节点的右子树仅包含键 大于 节点键的节点。
- 左右子树也必须是二叉搜索树。
右中左遍历即可。
class Solution {
private int sum;
public TreeNode convertBST(TreeNode root) {
sum = 0;
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);
}
}