剪枝
上下限递归的主要思路:
- 设每个节点必须在一个范围内: ( m i n , m a x ) (min, max) (min,max),不包含边界,若节点值超过这个范围,则返回 false
- 对于 node.left 范围肯定是 ( m i n , n o d e . v a l ) (min, node.val) (min,node.val)
- 对于 node.right 范围肯定是 ( n o d e . v a l , m a x ) (node.val, max) (node.val,max)
- 一开始不知道 min,max 则取 java 中长整数的最小Long.MIN_VALUE、最大值Long.MAX_VALUE
相关习题:
验证二叉搜索树-力扣 98 题
求范围和-力扣 938 题
满老师这两道题也用了这个思路,叫做上下限递归
Leecode习题
669. 修剪二叉搜索树
方法一:递归
class Solution {
public TreeNode trimBST(TreeNode node, int low, int high) {
if(node == null) return null;
// 不在(删)
if(node.val<low){
return trimBST(node.right,low,high);
}
if(node.val>high){
return trimBST(node.left,low,high);
}
//在(找到了,删除)
root.left = trimBST(root.left,low,high);
root.right = trimBST(root.right,low,high);
return root;
}
}
方法二:迭代
1.反反复复处理根节点,直到根节点在目标范围内
2.处理左子树(此时根节点在范围内,所以左边只有小于low)
3.处理右子树(只考虑大于high的情况)
class Solution {
public TreeNode trimBST(TreeNode root, int low, int high) {
if(root == null) return null;
// 处理根节点
while(root!=null&&(root.val<low||root.val>high)){
if(root.val<low){
root = root.right;
}else{
root = root.left;
}
}
TreeNode cur = root;
//处理左子树
while(cur !=null){
while(cur.left!=null&&cur.left.val<low){
cur.left = cur.left.right;
}
cur = cur.left;
}
// 处理右子树
cur = root;
while(cur !=null){
while(cur.right!=null&&cur.right.val>high){
cur.right = cur.right.left;
}
cur = cur.right;
}
return root;
}
}
108.将有序数组转换为二叉搜索树
二叉搜索树的中序遍历就是有序数组
方法一:递归(分治法)
用二分法,先找到中间节点,前面的就作为左子树,后面就是右子树
三要素:
1.返回值:为了建立新的父子关系
2.停止条件:输入数组长度为1或者不存在了
3.单层循环:中间节点作为根节点,前面的就作为左子树,后面就是右子树
class Solution {
public TreeNode sortedArrayToBST(int[] nums) {
return genBST(nums,0,nums.length-1);
}
private TreeNode genBST(int[] nums,int l,int r){
if(l>r) return null;
if(l==r) return new TreeNode(nums[l]);
int mid = (l+r)>>1;
TreeNode root = new TreeNode(nums[mid]);
root.left = genBST(nums,l,mid-1);
root.right = genBST(nums,mid+1,r);
return root;
}
}
1008 题-根据前序遍历结果构造二叉搜索树
方法一:分治法(同上)满老师解析
关键:找到根节点,以及对应的索引,确定哪一块表示左子树和右子树
上一题通过(l+r)>>2表示中间节点,而这道题一直0是根节点,所以需要通过循环找到比nums[0]小的,确定左子树的范围。
class Solution {
public TreeNode bstFromPreorder(int[] nums) {
return genBTS(nums,0,nums.length-1);
}
private TreeNode genBTS(int[] nums,int s,int e){
if(s>e) return null;
TreeNode root = new TreeNode(nums[s]);
int index = s+1;
while(index<=e){
if(nums[index]>nums[s]){
break;
}
index++;
}
root.left = genBTS(nums,s+1,index-1);
root.right = genBTS(nums,index,e);
return root;
}
}
538. 把二叉搜索树转换为累加树
方法一:递归
- 返回值无(主要用于建立父子关系,若父子关系没变,无需返回值)
- 停止条件:root==null
- 单层递归逻辑:反中序遍历(右我左),遍历一个节点累加一次
class Solution {
int sum =0;
public TreeNode convertBST(TreeNode root) {
revMid(root);
return root;
}
private void revMid(TreeNode root){
if(root == null) return;
revMid(root.right);
sum += root.val;
root.val =sum;
revMid(root.left);
}
}
方法二:反中序遍历(右我左)----迭代
class Solution {
public TreeNode convertBST(TreeNode root) {
if(root == null) return null;
int pre =0;
LinkedList<TreeNode> stack = new LinkedList<>();
TreeNode cur = root;
while(cur!=null||!stack.isEmpty()){
if(cur!=null){
stack.push(cur);
cur = cur.right;
}else{
cur = stack.pop();
cur.val +=pre;
pre = cur.val;
cur = cur.left;
}
}
return root;
}
}