• 博客园logo
  • 会员
  • 周边
  • 新闻
  • 博问
  • 闪存
  • 众包
  • 赞助商
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
fangleSea
博客园    首页    新随笔    联系   管理    订阅  订阅
代码随想录|二叉树(最后一章)

530.二叉搜索树的最小绝对差 

501.二叉搜索树中的众数 

236. 二叉树的最近公共祖先 

235. 二叉搜索树的最近公共祖先 

701.二叉搜索树中的插入操作 

450.删除二叉搜索树中的节点 

669. 修剪二叉搜索树 

108.将有序数组转换为二叉搜索树 

538.把二叉搜索树转换为累加树 

总结篇 

530.二叉搜索树的最小绝对差

注意 搜索树:想到中序遍历的从小到大的有序结果

双指针的应用,全局的设定。

/**
 * 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 ans = Integer.MAX_VALUE;
    public TreeNode pre_node = null;
    public int getMinimumDifference(TreeNode root) {
        search(root);
        return ans;
    }
    public void search(TreeNode node){
        if(node == null) return;
        search(node.left);
        if(pre_node != null) ans = Math.min(ans, node.val-pre_node.val);
        pre_node = node;
        search(node.right);
    }
}

501.二叉搜索树中的众数

搜索树:中序遍历的有序数列 

和上面那题一样 使用双指针

前后进行对比

注意pre_node的更新位置实在搜索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 {
    ArrayList<Integer> ans = new ArrayList<Integer>();
    int max_time = 0;
    int count = 0;
    TreeNode pre_node = null;
 
    public int[] findMode(TreeNode root) {
        search(root);
        int[] ansList = new int[ans.size()];
        for(int i = 0; i < ans.size(); i++){
            ansList[i] = ans.get(i);
        }
        return ansList;
    }
 
    public void search(TreeNode node){
        if (node == null) return;
        search(node.left);
        //计数
        if (pre_node == null || pre_node.val != node.val){
            count = 1;
        }
        else{
            count ++;
        }
        //更新
        if(count == max_time) ans.add(node.val);
        if(count > max_time){
            ans.clear();
            max_time = count;
            ans.add(node.val);
        }
        pre_node = node;
        search(node.right);
    }
}

236. 二叉树的最近公共祖先

最近公共祖先想到的是回溯的方法,在找到一个后找第二个点,如果左右都有返回响应,则表明这个点就是她们的公共祖先点

递归问题 回溯思想

想终止条件:找到了,或者到头了

探索:左边,右边

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if (root == null || root.val == p.val || root.val == q.val) return root;
        TreeNode left = lowestCommonAncestor(root.left, p, q);
        TreeNode right = lowestCommonAncestor(root.right, p, q);
        if(left != null && right != null) return root;
        if(left != null) return left;
        if(right != null) return right;
        return null;
    }
}

 

235. 二叉搜索树的最近公共祖先

因为是搜索数,找到两个点p,q的最近公共祖先就是找[p,q]区间内遇到的第一个点

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
 
class Solution {
 
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if(root == null) return null;
        if(root.val > p.val && root.val > q.val) return lowestCommonAncestor(root.left, p, q);
        if(root.val < p.val && root.val < q.val) return lowestCommonAncestor(root.right, p, q);
        return root;
    }
}

701.二叉搜索树中的插入操作

注意考虑头指针就是null的情况

/**
 * 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 insertIntoBST(TreeNode root, int val) {
        if(root == null) return new TreeNode(val);
        search(root, val);
        return root;
    }
    public void search(TreeNode node, int val){
        if (node.val > val){
            if(node.left == null) {
                node.left = new TreeNode(val);
                return;
            }
            search(node.left, val);
        }
        else{
            if(node.right == null){
                node.right = new TreeNode(val);
                return;
            }
            search(node.right, val);
        }
    }
}

可以改写为

class Solution {
    public TreeNode insertIntoBST(TreeNode root, int val) {
        if (root == null) // 如果当前节点为空,也就意味着val找到了合适的位置,此时创建节点直接返回。
            return new TreeNode(val);
            
        if (root.val < val){
            root.right = insertIntoBST(root.right, val); // 递归创建右子树
        }else if (root.val > val){
            root.left = insertIntoBST(root.left, val); // 递归创建左子树
        }
        return root;
    }
}

450.删除二叉搜索树中的节点

我的第一版本编写

注意边界的思考:在做二叉树问题的时候,每一次判断都要思考会不会是null的情况,如果是null应该怎么做,之前是否有过滤掉这个问题

/**
 * 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 deleteNode(TreeNode root, int key) {
        if(root == null) return null;
        if(root.val == key){
            root = search(root);
            return root;
        }
        TreeNode temp = root;
        boolean flag = false;
        while(temp != null){
            if(temp.val > key) {
                if(temp.left == null){
                    flag = true;
                    break;
                }
                if(temp.left.val == key) break;
                temp = temp.left;
            }
            else {
                if(temp.right == null){
                    flag = true;
                    break;
                }
                if(temp.right.val == key) break;
                temp = temp.right;
            }
 
        }
        if (flag || temp == null) return root;
        if(temp.left != null && temp.left.val == key) temp.left = search(temp.left);
        if(temp.right != null && temp.right.val == key) temp.right = search(temp.right);
        return root;
    }
 
    public TreeNode search(TreeNode root){
        if(root.right == null) return root.left;
        if(root.left == null) return root.right;
        TreeNode temp = root.right;
        while(temp.left != null) temp = temp.left;
        temp.left = root.left;
        return root.right;
    }
}

可以简化为向两边寻找的方式

class Solution {
    public TreeNode deleteNode(TreeNode root, int key) {
        root = delete(root,key);
        return root;
    }
 
    private TreeNode delete(TreeNode root, int key) {
        if (root == null) return null;
 
        if (root.val > key) {
            root.left = delete(root.left,key);
        } else if (root.val < key) {
            root.right = delete(root.right,key);
        } else {
            if (root.left == null) return root.right;
            if (root.right == null) return root.left;
            TreeNode tmp = root.right;
            while (tmp.left != null) {
                tmp = tmp.left;
            }
            root.val = tmp.val;
            root.right = delete(root.right,tmp.val);
        }
        return root;
    }
}

669. 修剪二叉搜索树

给定一个二叉搜索树,同时给定最小边界L 和最大边界 R。通过修剪二叉搜索树,使得所有节点的值在[L, R]中 (R>=L) 。你可能需要改变树的根节点,所以结果应当返回修剪好的二叉搜索树的新的根节点。

理解了最关键部分了我们再递归三部曲:

  • 确定递归函数的参数以及返回值

这里我们为什么需要返回值呢?

因为是要遍历整棵树,做修改,其实不需要返回值也可以,我们也可以完成修剪(其实就是从二叉树中移除节点)的操作。

但是有返回值,更方便,可以通过递归函数的返回值来移除节点。

  • 确定终止条件

修剪的操作并不是在终止条件上进行的,所以就是遇到空节点返回就可以了。

  • 确定单层递归的逻辑

如果root(当前节点)的元素小于low的数值,那么应该递归右子树,并返回右子树符合条件的头结点

/**
 * 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 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;
    }
}

108.将有序数组转换为二叉搜索树

将一个按照升序排列的有序数组,转换为一棵高度平衡二叉搜索树。

本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1。

注意是左右子树的高度差的绝对值不超过1!!!!

所以不能是劈叉那种

这里想 每个的高度差的绝对值不超过1, 形成了重复,可以使用递归进行解决。

中间节点为中间的数字,两边重复形成。

/**
 * 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 sortedArrayToBST(int[] nums) {
        return search(nums, 0, nums.length);
    }
    public TreeNode search(int[] nums, int left, int right){
        if (left >= right) return null;
        int mid = left + (right - left)/2;
        TreeNode temp = new TreeNode(nums[mid]);
        temp.left = search(nums, left, mid);
        temp.right = search(nums, mid+1, right);
        return temp;
    }
}

538.把二叉搜索树转换为累加树

/**
 * 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 {
    int sum = 0;
    public TreeNode convertBST(TreeNode root) {
        if (root == null) return null;
        TreeNode temp = new TreeNode(0);
        temp.right = convertBST(root.right);
        sum += root.val;
        temp.val = sum;
        temp.left = convertBST(root.left);
        return temp;
    }
}

二叉树总结篇!!!

非常详细,值得二刷

https://programmercarl.com/二叉树总结篇.html#求二叉树的属性

 

posted on 2023-06-13 16:42  跪求个offer  阅读(17)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3