打卡第18天

#LCR 045. 找树左下角的值

自己直接用层序搞出来了,听了卡哥的递归的解法,有了启发,自己不会用递归的方法,主要是不知道最大深度应该怎么处理,就是不知道怎么知道此时是最大深度,卡哥用了一个变量来记录深度,通过比较来判断是否是大于最大深度,如果递归的是否发现大于最大深度,那么最大深度就改变成比它大的值,并将当前节点的val作为结果

#112. 路径总和

我用昨天求所有路径的方法,把所有的路径的结果放到List里面,如果list包含目标值就为true,反之false,但是这样做很冗余,正确应该是一旦遍历到结果就直接返回,剩下的就不再便利了,我知道应该写一个返回值类型为布尔的类型,我知道如果一个值的左子节点和右节点都为null时要判断遍历的路径和是否为目标值,如果是就直接返回true,但是我不知道遍历的节点不为叶子节点而是中间节点应该如何返回,导致用这种方法写不出来,卡哥的思路是因为调用的返回值为boolean型,如果boole值是true,说明结果为true,此时的返回值已经是遍历到根节点并计算了的了,是否要显式的使用回溯要判断之前对数据的处理会对之后平级的数据处理产生影响,比如对左子树不为空时进行操作,如果将传入的targetsum做targetsum-=root.left.val处理后,再将targetsum作为参数传入,而后面的右子树不为空时再传入targetsum,因为先前做了减的操作,因为左子树和右子树同级,传入前要跟传入左子树的数值一致所以左子树的处理后要加上。

/**
 * 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 boolean hasPathSum(TreeNode root, int targetSum) {
      if(root==null){
        return false;
      }
      targetSum=targetSum-root.val;
      if(root.left==null&&root.right==null&&targetSum==0){
        return true;
      }
       if(root.left==null&&root.right==null){
        return false;
      }
      if(root.left!=null){
       
        if(hasPathSum(root.left,targetSum)){
          return true;
          
        }
       
      }
      if(root.right!=null){
       
        if(hasPathSum(root.right,targetSum)){
          return true;
        }
       
      }
      return false;

    }
   

}

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

这个题的主要思路是分割,每次都根据后续和中序分割出根节点和左右子树的order数组,如此递归下去,直到找到根节点返回null,三步法,先确定返回值类型和参数,因为要求返回的是构造的二叉树,因此返回值类型是TreeNode,入参是中序和后续的数组,先确定终止条件,如果两个数组为空,那就说明结束,返回null,递归逻辑,通过后续的最后一个节点,可以判断在这一层的根节点是谁,通过根节点的值遍历中序数组,可以得到根节点的坐标,并根据根节点坐标分割出中序数组的左子树部分(数组根节点位置的左部分)和右子树部分(数组根节点位置的右部分),然后根据左子树部分的长度到后续数组找到后序数组的左子树部分(0,len)和右子树部分(0,end-1),然后让这层的根节点左子树指向dfs(中序左子树数组,后续左子树数组),右子树指向(中序右子树数组,后续右子树数组),最后返回根节点,这道题还有一个易错的点,就是区间的开闭,我们统一用左闭右开。

学习设计模式的笔记:

类之间的关系主要包括关联关系、聚合关系,组合关系,依赖关系、泛化关系和类和接口的关系,

关联关系:一个类是另一个类的成员变量,

单向关联:就是一个类是另一个类的成员变量,用单项箭头表示,拥有一个类的类型的成员变量的指向成员变量类型的类

双向关联:两个类互为对方的成员变量,uml图为没有箭头的直线

自关联:就是类似于树那样,自己为自己的成员变量,uml图为自己指向自己的箭头。

多重性关联:一个类有多个成员变量是另一个类的类型,uml图用单项箭头表示,拥有一个类的类型的成员变量的指向成员变量类型的类,并标注上1..3类似的字符。

聚合关系:一个类是另一个类的构造函数或者setter函数的入参,uml图用空菱形箭头表示,入参类型的类被箭头指。

组合关系:一个类型的对象控制着另一个类型的对象的生命周期,通常是一个类的构造方法中实例化另一个类,uml图表示跟聚合关系类似,只是变成了实心的菱形

依赖关系:就是一个类功能的实现需要使用另一个类的功能,驾驶员类的move方法需要依赖车的move方法来实现,uml图用虚线箭头表示,被依赖的类被箭头指

泛化关系:即一个类是另一个类的子类,uml图中用空心的三角箭头表示,由子类指向父类。

接口和实现关系:uml图用空心的三角虚线箭头表示,由实现指向接口。

面向对象的设计原则:

1、单一职责原则:就是一个类的不要有太复杂的功能(耦合度太高),就是引起一个类改变的原因只有一个,如一个类既有连接数据库的功能,又有处理数据库数据的功能,又有将数据处理和呈现的功能,就可以将这个类分割成三个类。

2、里氏替换原则:出现基类的地方都能被子类代替,因此我们在写参数的时候尽量用接口或者基类来写,运行时确定具体类型,方便以后

3、开闭原则:对拓展开放,对修改关闭,当出现新的功能需求时,如何尽量避免修改源代码来实现新的需求,抽象化是开闭原则的关键,当功能出现变化时,不需要对抽象层进行改动,只需要实现新的实现类即可

4、合成复用原则:需要使用其他类的功能时尽量通过引入成员变量,而不是继承,因为继承或者实现,需要实现一些可能用不到的方法,还可能导致接口的部分功能暴露给用户

5、接口隔离原则:确定好接口的粒度,不能粒度太大导致功能太多,也不能粒度太小导致接口泛滥

6、依赖倒置原则:抽象不依赖于细节,细节依赖于抽象,就是在成员变量类型声明、参数列表的参数的类型声明、返回值类型应当使用尽量高级的抽象(接口或者抽象类)即面向接口编程,而不要使用具体实现的类,这要求我们在子类中应当只实现高级抽象声明的方法,而不要给出对余的方法,导致无法调用子类实现的方法,这样无需改源代码就可以拓展修改系统功能,满足开闭原则要求。

7、迪米特法则:一个实体类要尽量少的跟其他实体类产生交互。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值