Amber-Leedcode-Java-代码随想录打卡十七、十八、二十、二十一天、二十二天、二十三天(二叉树汇总)

文章记录了一个学习者在11天内逐步深入理解和解决二叉树相关算法(如平衡二叉树、路径和、左叶子之和等)的过程,强调了代码实践和逻辑思维的重要性。作者从迷茫到逐渐掌握,展示了编程学习中的成长和反思。
摘要由CSDN通过智能技术生成

前言

路漫漫其修远兮,在摆烂了三天后今天猛追啊,哈哈哈,写了比较多的题总结一下就是,虽然可以写出来但还是迷迷糊糊感觉没有十分通透,继续加油吧。。


更新 1-30日

代码是一场逻辑游戏。,,,。。今天又把以下题目都做了一遍,感觉好了很多 


更新 1-31日

把22天的写完了,终于leedcode破百了啊啊啊


更新 2-1日

二叉树完结了,写leedcode好像已经成了一个习惯了,很开心,希望可以越写越快

110.平衡二叉树

主要要明白,是高度差大约1,理解高度的概念,所以是对高度进行操作

一开始写了一遍没有写出来,

然后又写了一遍还没有写出来。。

1.笔记:

2.代码 

要明白返回的是树的高度 - 因此出现的几种情况

-左子树高度 == -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 {
    int getHeight(TreeNode root){
        if (root == null){
            return 0;
        }
        if (root.left == null && root.right == null){
            return 1;
        }
        int left = getHeight(root.left);
        if (left == -1){
            return -1;
        }
        int right = getHeight(root.right);
        if (right == -1){
            return -1;
        }
        int result = Math.abs(left - right);
        if (result > 1){
            return -1;
        }else{
            return Math.max(left,right)+1;
        }
    }
    public boolean isBalanced(TreeNode root) {
        int result = getHeight(root);
        if (root == null){
            return true;
        }
        if (result == -1){
            return false;
        }else{
            return true;
        }
    }
}

● 257. 二叉树的所有路径

这个题还是有难度的,尤其是在类型转换的方面。

更新 -1.30

-第二遍做感觉好多了-但是在这里出现了问题

要判断左右节点是否为空才可以删除

1.笔记

2.code 

/**
 * 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 {
    void getPath(TreeNode node,ArrayList<Integer> path,List<String> result){
        path.add(node.val);
        if (node.left == null && node.right == null){
            StringBuilder sb = new StringBuilder();
            for(int i = 0;i < path.size();i++){
                sb.append(path.get(i));
                if (i < path.size() - 1 ){
                    sb.append("->");
                }
            }
            result.add(sb.toString());
            return;
        }
        if (node.left != null){
            getPath(node.left,path,result);
            path.remove(path.size()-1);
        }
        if (node.right != null){
            getPath(node.right,path,result);
            path.remove(path.size()-1);
        }
        return;
    }

    public List<String> binaryTreePaths(TreeNode root) {
        ArrayList<Integer> path = new ArrayList<>();
        List<String> result = new ArrayList<>();
        getPath(root,path,result);
        return result;
    }
}

404.左叶子之和 

自己虽然写出来了,但是还是不太确定,比较糊涂了属于


更新 1.30

第二遍做很快就做出来了,先写遍历,然后在判断停止条件,这个比较简单,记得要添加一个符号判断是不是left,因为后续无法判断出来。

code

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

    void getSum(TreeNode node,boolean left_bool){

        if (node == null){
            return;
        }
        if (node.left == null && node.right == null && left_bool == true){
            sum = sum + node.val;
            return;
        }
        getSum(node.left,true);
        getSum(node.right,false);
    }
    public int sumOfLeftLeaves(TreeNode root) {
        getSum(root,false);
        return sum;

    }
}

 513.找树左下角的值

自己写的时候特别茫然,不太会。。。不得不说

遇到了点挫折,不过写出来了


更新 - 1.30

比较快就写出来了,但是要注意deep++和deep + 1 的区别

且还要明白的是,找的是最底层的左下角的值,注意审题

在Java中,deep++是一个后缀递增运算符,它的含义是在表达式的值被使用后,变量deep的值才增加1。如果您将您的代码中的deep+1更改为deep++,它将对代码的行为产生重要的影响。

假设您的原始代码是这样的:

findLeft(root.left, deep + 1);
findLeft(root.right, deep + 1);

在这里,每次调用findLeft时,您都向它传递了deep当前值加1。这样做的效果是,每次递归调用都将深度增加1,但不会改变当前递归层的deep的值。

但是,如果您将代码更改为:

findLeft(root.left, deep++);
findLeft(root.right, deep++);

这将会导致不同的行为。在第一次调用findLeft(root.left, deep++)时,deep的当前值被传递给方法,但在方法执行之后deep的值增加了1。这意味着当执行第二个调用findLeft(root.right, deep++)时,deep的值已经是第一次调用后的值。

这种更改将导致对左子树和右子树的递归调用使用不同的深度值,这可能并不是您想要的行为,特别是在处理二叉树递归问题时,通常我们希望在同一层的左右子树上使用相同的深度值。

总之,使用deep++会改变递归调用中深度值的递增方式,这可能会导致您的代码的逻辑出现问题,特别是如果您的逻辑依赖于在同一树层上使用相同的深度值。正确的做法通常是使用deep + 1,这样可以确保每一层的递归调用都使用正确的深度值。

code

/**
 * 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 left_val;
    int max_deep;
    void findLeft(TreeNode root,int deep){
        if (root == null){
            return;
        }
        if (root.left == null && root.right == null && deep > max_deep){
            left_val = root.val;
            max_deep = deep;
        }
        findLeft(root.left,deep+1);
        findLeft(root.right,deep+1);
    }
    public int findBottomLeftValue(TreeNode root) {
        findLeft(root,1);
        return left_val;
    }
}

 112. 路径总和  

顺利解决

113.路径总和ii

顺利解决,但是要看path到赋值情况一直在变化

106.从中序与后序遍历序列构造二叉树 

说实话这个一开始没有什么想法        

去看题解了。


更新 - 虽然写出来了,但是还是迷迷糊糊的

笔记

code

/**
 * 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 find (int[] inorder, int tmp_mid){
        for (int i = 0 ;i < inorder.length;i++){
            if (inorder[i] == tmp_mid){
                return i;
            }
        }
        return 0;
    }
    TreeNode buid(int[] inorder, ArrayList<Integer> postorder,int left,int right,int index_all){
        if (index_all < 0){
            return null;
        }
        int tmp_mid = postorder.get(index_all);
        int mid = find(inorder,tmp_mid);
        TreeNode node_result = new TreeNode(inorder[mid]);
        if (left > right){
            return null;
        }else if (left == right){
            postorder.remove(postorder.size()-1);
            return node_result;
        }
        postorder.remove(postorder.size()-1);
        node_result.right = buid(inorder,postorder,mid + 1,right,postorder.size() - 1);
        node_result.left = buid(inorder,postorder,left,mid - 1,postorder.size() - 1);
        return node_result;
    }

    public TreeNode buildTree(int[] inorder, int[] postorder) {
        ArrayList<Integer>  post_arraylist = new ArrayList<>();
        for (int i = 0;i < postorder.length;i++){
            post_arraylist.add(postorder[i]);
        }
        TreeNode node_result = buid(inorder,post_arraylist,0,postorder.length - 1,postorder.length-1);
        return node_result;   
    }
}

105.从前序与中序遍历序列构造二叉树

说实话这个一开始没有什么想法      

更新 - 与前一个大同小异-感觉自己的代码有点冗余,可以再写一遍明天。

code

/**
 * 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 find (int[] inorder, int tmp_mid){
        for (int i = 0 ;i < inorder.length;i++){
            if (inorder[i] == tmp_mid){
                return i;
            }
        }
        return 0;
    }
    TreeNode buid(int[] inorder, ArrayList<Integer> postorder,int left,int right,int index_all){
        if (index_all < 0){
            return null;
        }
        int tmp_mid;
        if (postorder.size() > 0){
            tmp_mid = postorder.get(0);
        }else{
            return null;
        }
        int mid = find(inorder,tmp_mid);
        TreeNode node_result = new TreeNode(inorder[mid]);
        if (left > right){
            return null;
        }else if (left == right){
            postorder.remove(0);
            return node_result;
        }
        postorder.remove(0);
        node_result.left = buid(inorder,postorder,left,mid - 1,0);
        node_result.right = buid(inorder,postorder,mid + 1,right,0);
        return node_result;
    }
    public TreeNode buildTree(int[] inorder, int[] postorder) {
        ArrayList<Integer>  post_arraylist = new ArrayList<>();
        for (int i = 0;i < postorder.length;i++){
            post_arraylist.add(inorder[i]);
        }
        TreeNode node_result = buid(postorder,post_arraylist,0,postorder.length - 1,0);
        return node_result;   
    }
}

654.最大二叉树 

遇到一点问题,基本上解决了

 617.合并二叉树 

已解决

 700.二叉搜索树中的搜索 

还是有一些缺陷。。。。。啊啊啊啊啊啊要疯了

 98.验证二叉搜索树

写完了,记得要更新最小值。。

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

变为中序遍历,这个题有技巧

 501.二叉搜索树中的众数 

使用hashset来保证数组内元素的唯一性。。啊啊做了好久

/**
 * 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 count = 1;
    int max_count = 1;
    HashSet<Integer> result = new HashSet<Integer>();
    TreeNode pre;

    void action(TreeNode cur){
        if (pre == null){
            count = 1;
        }else if (cur.val == pre.val){
            count++;
        }else if (cur.val != pre.val){
            count = 1;
        }
        if (count > max_count){
            max_count = count;
            result.clear();
            result.add(cur.val);
            }else if (count == max_count){
                result.add(cur.val);
            }
        pre = cur;
    }

    void find_dfs(TreeNode cur){
        if (cur == null){
            return;
        }
        find_dfs(cur.left);
        action(cur);
        find_dfs(cur.right);
    }

    public int[] findMode(TreeNode root) {
        find_dfs(root);
        int[] result_array = new int[result.size()];
        int num = 0;
        for (int i : result){
            result_array[num] = i;
            num++;
        }
        return result_array;
    }
}

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

听说本题较难,先看了视频

这个题的要点在于 - 首先返回的是treenode,我一开始返回的是boolean,因此不可以

而且要分情况讨论 (左为空,右不为空,返回left之类的节点,可以解决p或者q为答案的情况,如果设置为boolean就不好判断了)

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {

    TreeNode traveral(TreeNode node,TreeNode p, TreeNode q){
        if (node == null){
            return null;
        }
        if (node.val == p.val || node.val == q.val){
            return node;
        }
        TreeNode left = traveral(node.left,p,q);
        TreeNode right = traveral(node.right,p,q);
        if (left != null && right != null){
            return node;
        }else if (left!= null && right == null){
            return left;
        }else if (left == null && right != null){
            return right;
        }
        return null;

    }

    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        TreeNode common_ancestor = traveral(root,p,q);
        return common_ancestor;

        
    }
}

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

虽然做出来了,但真的是稀里糊涂而且凭借直觉,,。。

/**
 * 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) {
        TreeNode right = null;
        TreeNode left = null;
        TreeNode node = root;
        if (node == null){
            return null;
        }
          if (node.val == p.val || node.val == q.val){
            return node;
        }
        if (node.val > p.val){
            left = lowestCommonAncestor(node.left,p,q);
        }
        if (node.val < q.val){
            right = lowestCommonAncestor(node.right,p,q);
        }
        if (left == null && right != null){
            return right;
        }else if (left != null && right != null){
            return node;
        }else if (left != null && right == null){
            return left;
        }
        return node;
        
    }
}

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

  2. 思考

一开始想的是中序遍历后插入第一次大于的值但小于右边的位置,但是问题是左右孩子应该怎么找啊?哦,把val变成一个treenode就好了,然后他的left为左边的值,right为右边。right应该怎么找呢??

那返回的值的话,应该是返回啥

插入为叶子结点就好了。。。。。转换完成思路后就变得比较简单。。

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

还是比较顺利的,但是要注意的情况是 - 当右边不为空时候,要把左子树插入右边的最左下角才可以,要迭代一下,最开始写的时候疏忽了。

/**
 * 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){
            if (root.right != null){
                if (root.left == null){
                    root = root.right;
                }else{
                TreeNode tmp = root.left;
                root = root.right;
                TreeNode cur = root;
                while (cur.left != null){
                    cur = cur.left;
                }
                cur.left = tmp;
                }
                return root;
            }else if (root.left != null){
                root = root.left;
            }else{
                return null;
            }
        }else if (root.val < key){
            root.right = deleteNode(root.right,key);
        }else if (root.val > key){
            root.left = deleteNode(root.left,key);
        }
        return root;


    }
}



 669. 修剪二叉搜索树 

/**
 * 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);
        }else if (root.val > high){
            return trimBST(root.left,low,high);
        }
        if (root.left != null ){
            root.left = trimBST(root.left,low,high);
        }
        if(root.right != null){
            root.right = trimBST(root.right,low,high);
        }
        return root;
    }
}

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

比较简单,顺利做出来了

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;
        }
        convertBST(root.right);
        root.val = sum + root.val;
        sum = root.val;
        convertBST(root.left);
        return root;
    }
}

总结篇 ​​​​​​​

来自

 代码随想录知识星球 (opens new window)成员:青 (opens new window),所画

总结:

  1. 状态:未完结
  2. 学习很多个小时
  3. 困难:
  4. 待解决问题:
  5. 今日收获:
  6. 来源:代码随想录
  • 7
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值