- 博客(61)
- 收藏
- 关注
原创 递归转非递归的一些思考
(英语:Recursion),又译为,在与中,是指在的定义中使用函数自身的方法。递归一词还较常用于描述以方法重复事物的过程。例如,当两面镜子相互之间近似平行时,镜中嵌套的图像是以无限递归的形式出现的。也可以理解为自我复制的过程。简而言之,在计算机中,递归就是指在一个函数中出现了自己调用自己的行为。上面的例子用来求解一个n的阶乘,在f函数中,出现了f自己调用自己的行为,因此f就是一个递归函数。
2023-04-26 15:08:58
741
1
原创 274. H 指数
题目中给出的H指数定义比较绕,如果查询百度百科可以发现一个更加简单的H指数的定义:那么问题就变得很简单了,将citations数组逆序排序,然后找到当前的下标i,返回i即可。比如示例1中的[6,5,3,1,0],发现i=3的时候满足条件,因此H指数为3。解题的时候并没有采用逆序排序的方法,原因是Arrays工具类仅支持对基本类型数组升序排序,此时该如何做呢?首先百度百科中的序号是从1开始的,而数组下标是从0开始的,百度百科中说的是直到某篇论文的序号大于该论文被引次数,序号减1就是H指数。
2023-02-01 20:29:05
276
原创 217. 存在重复元素
使用一个Set集合,依次遍历数组中的元素,每遍历一个元素,先判断当前元素是否存在于Set集合中,如果存在,那么返回true,说明出现了重复元素(题目要求至少一次),如果遍历完所有元素,依然没有提前返回true,那么返回false,说明数组中的元素互不相同。
2023-01-23 10:25:23
112
原创 74. 搜索二维矩阵
采用两次二分的方式,第一次二分用于找到target在二维矩阵中的行标,第二次二分只需要对找到的行进行二分查找即可。时间复杂度分析,如果矩阵的行为m,列为n,那么二分搜索行时间复杂度是。知道目标值所在行之后,只需要对该行的数据二分查找target即可。,确定行后,二分搜索该行元素时时间复杂度是。
2023-01-19 21:45:18
966
原创 Spring中Bean的生命周期
Java Bean的生命周期指的是:Bean的创建、初始化、销毁Spring为我们提供了多种方式介入Bean的生命周期,即在生命周期中加入额外的自定义逻辑。Bean的创建:指的是Spring通过构造方法,实例化Bean的过程。属性赋值。之后才是Bean的初始化过程,Bean的初始化过程可以由用户直接介入,指定Bean的初始化逻辑,怎么介入下面会介绍。
2023-01-19 16:35:12
2100
原创 链表中点技巧:快慢指针定位链表中点
单链表的节点数目可能是奇数或者偶数,奇数节点的链表中点是唯一的,偶数节点的链表中点有两个,分别是上中点和下中点,如下图所示:
2023-01-18 16:20:03
543
原创 三、equals重写规范
如果需要对子类特定的部分进行比较,那么不要使用instanceOf的方式,如果所有子类的比较规则都是相同的,那么可以使用instanceOf方法,然后在父类中声明该比较方法,同时将该方法声明为final类型,这样可以避免子类对该方法进行重写。Java的equals方法用来比较两个对象是否相等,该方法是继承自Object类,因此所有的类都可以使用该方法,但是一般类如果涉及到后面的比较的时候,都需要重写该方法,因为Object中提供的实现默认比较的是两个对象的地址。
2022-11-02 21:10:04
796
原创 二、代码块的加载顺序
下面的程序最终会输出username=6,原因是静态代码块会随着类加载的时候被执行,调用类的静态方法或者访问类的静态属性以及实例化类的对象或者调用Class.forName()的时候都会触发类的加载,这个时候就会出发静态代码块的执行。下面的程序最终会输出username=5,原因是构造代码块最终会被放置到构造函数的第一行执行,构造代码块之间按照声明的顺序进行执行,可以在前向声明的代码块中对成员变量进行初始化,但是不能前向使用变量(仅能做初始化),也就意味着下面的注释代码如果打开会报错。
2022-11-02 21:06:26
616
原创 一、访问控制修饰符
privatedefaultprotectedpublicprivate被private修饰的字段或者方法仅在本类中可见default字段或者方法没写访问控制修饰符的情况下,默认就是该访问控制级别,属于default级别的字段或者方法仅在被包内可见protected被protected修饰的字段或者方法,仅在本包可见,或者对其他包的子类中可见,其他包的不同子类之间仍然不可见。public最宽松的访问控制修饰符,被public修饰的字段或者方法在整个工程中可见。
2022-11-02 21:02:51
630
原创 五、原型模式
对象的拷贝又可以分为浅拷贝和深拷贝两种,所谓的浅拷贝指的是对引用类型,只是对引用本身进行了克隆,克隆的对象和以前的对象的引用指向同一块内存空间,如果该引用指向的是可变的对象,那么在某些场景下,新对象通过该引用对对象的修改,旧对象也可见,反之亦然。原型模式指的是,以某个对象为原型,产生一份调用该对象的某个接口方法,可以先对该对象的克隆拷贝,在Java中可以使用两种机制实现原型模式,一种是序列化机制,一种是来自Object类的clone方法。可以这么理解原型模式就是指的对象的拷贝。
2022-11-02 20:42:41
271
原创 四、抽象工厂模式
产品族指的是位于不同产品等级的且具有内在联系的多个产品构成的集合,比如手机产品和充电器产品,这是两个独立的产品,手机产品位于手机等级结构,充电器产品位于充电器等级结构中,那么手机产品和充电器产品就位于两个不同的产品等级结构中,因此二者构成一个产品簇。产品等级指的是产品的继承结构,比如手机产品,一般会有一个抽象的手机父类,然后再有具体的手机产品,比如华为手机,小米手机,苹果手机等,那么手机产品之间就形成了一个继承等级结构,所有的具体手机都继承自抽象手机类,就说手机产品构成一个产品等级。
2022-11-02 20:40:01
163
原创 三、工厂方法模式
无需改动现有的工厂类的代码,因此工厂方法模式很好的解决了简单工厂模式中,因此产品类扩展,而导致的工厂类代码的修改问题,很好的遵守了开闭原则。工厂方法模式将工厂类进行了抽象,在简单工厂模式中,只有一个简单工厂类,该简单工厂类并没有向上形成任何抽象,而工厂方法模式通过对工厂本身提供一个抽象层,并在该抽象层中定义了一个抽象的产品创建方法,子类工厂通过实现该方法完成具体产品的创建,该抽象方法也就是工厂方法。
2022-11-02 20:38:38
201
原创 二、简单工厂模式
简单工厂模式最大的问题就是扩展性问题,如果产品类别比较少,或者类别数目变化不大,那么使用简单工厂模式可以很好的对程序解耦,但是一但需要增加或者减少大量的产品类的时候,必须要修改简单工厂的代码,这不符合程序的开闭原则,同时简单工厂的职责过重,一个工厂类负责多个产品的创建,也违背了单一职责原则。简单工厂模式,故名思义就是简单,在产品类不是很多的时候,使用简单工厂可以很好的将产品类的创建和客户端代码解耦合,只要客户端和简单工厂创建产品的接口约定不变,那么产品类的创建细节可以随意改变。
2022-11-02 20:36:43
125
原创 一、设计模式七大设计原则
设计模式的七大设计原则是设计模式的基石,基本上23种设计模式的指导思想就是这七大设计原则。可以这么认为如果将设计模式比喻为盖房子的最佳实践,那么设计模式的七大原则就是指导盖房子过程中,应该怎么设计,应该怎么选材料等。单一职责原则里氏替换原则接口隔离原则开闭原则迪米特法则(最少知道原则)依赖倒置原则组合优先于继承原则关联关系。
2022-11-02 20:34:54
196
原创 六、单例模式
这里要先说明一下,instance在多个线程之间不存在内存可见性问题,因为有锁的存在,线程在执行临界区代码的时候,会将对共享变量的修改直接写回内存,因此instance不会存在内存可见性问题,这里导致问题的是new Singleton()可能会发生重排序,没错,就是因为这个重排序导致某个线程可能访问到未初始化完全的对象,从而可能导致错误。将单例对象定义成一个枚举类,枚举类的成员天然就是单例的,并且还不可以被序列化,因此可以防止因为序列化产生多个对象,这也是Effective Java里面推荐的方式。
2022-11-02 20:27:23
197
原创 docker安装mysql(单体)
放到这几个地方,mysql才会识别,并且如果这几个地方如果都有配置文件,那么mysql的加载顺序将严格按照上图输出的顺序,按照我的理解,前面的配置项将会被后面的配置项覆盖,这里我们选择的是在。文件夹下面挂载我们的配置文件,但是进入容器后,会发现改目录下面并没有配置文件,但是。文件拷贝到宿主机,然后将其移动到宿主机中。,把mysql的配置文件。下面有,因此我们只需要把。对应的数据卷下即可。
2022-09-17 10:50:54
417
原创 Mac(M1芯片)通过Docker安装Nacos
如果直接使用,那么可能会出现容器启动不了的情况,原因是上述指令拉取的镜像的版本默认是latest,很有可能该版本不支持arm架构。
2022-08-21 11:14:07
2545
原创 设计模式之职责链模式(责任链模式)
FilterChain其他辅助类测试代码4.1.3 基本原理讲解FilterChain中维护了一个Filter列表,该列表是数组实现,并且维护了一个curPos指针,用来指示当前经过的是第几个处理器。每次调用FilterChain的doFilter方法,都会让curPos+1,为了能让请求继续被下一个Filter处理,我们只需要实现链式调用curPos+1位置上的Filter即可,直到最后一个处理器被调用,这个时候再去调用HttpServlet的处理方法,完成对消息的处理。怎
2022-06-21 10:59:03
1351
原创 一、数据结构系列(堆篇)
堆结构是一棵完全二叉树,和普通的完全二叉树不同,堆对树中节点的取值做了如下的限制:【1】对于堆中的任意节点,它的值总是大于其左右孩子的取值。【2】对于堆中的任意节点,它的值总是小于其左右孩子的取值。如果限制规则是【1】,那么称这种堆为大顶堆。如果限制规则是【2】,那么称这种堆为小顶堆。堆顶一定始终存放着整个堆中最大值或者最小值,这取决于当前是大顶堆还是小顶堆。如果对堆中的每一个节点从上到下,从左到右的顺序进行编号,编号从开始那么节点编号存在如下关系由于堆是一棵完全二叉树,因为完全二叉树的特殊性,除了最后两层
2022-06-09 14:29:03
404
原创 工厂方法模式
工厂方法模式属于GoF中23种设计模式中的创建型模式,工厂方法模式可以很好的遵循开闭原则,相较于简单工厂模式,新增新的产品类不需要修改原有项目中的代码,只需要新增工厂类即可。工厂方法模式定义了一个创建产品的接口,子类实现该接口完成具体产品的创建,也就是说工厂方法模式将产品的创建延迟到了子类,由子类决定创建哪一种产品。...
2022-06-08 16:18:52
56
原创 简单工厂模式学习总结
简单工厂模式最大的问题就是扩展性问题,如果产品类别比较少,或者类别数目变化不大,那么使用简单工厂模式可以很好的对程序解耦,但是一但需要增加或者减少大量的产品类的时候,必须要修改简单工厂的代码,这不符合程序的开闭原则,同时简单工厂的职责过重,一个工厂类负责多个产品的创建,也违背了单一职责原则。简单工厂模式,故名思义就是简单,在产品类不是很多的时候,使用简单工厂可以很好的将产品类的创建和客户端代码解耦合,只要客户端和简单工厂创建产品的接口约定不变,那么产品类的创建细节可以随意改变。
2022-06-08 15:35:08
99
原创 随笔-记一次ThreadLocal的调用链
随笔-记一次ThreadLocal的调用链一、ThreadLocal的基本作用每一个线程可以拥有若干个ThreadLocal对象,线程的私有数据可以存放在ThreadLocal中,存放进ThreadLocal中的数据仅被当前线程可见,不会引起数据竞争,因此ThreadLocal也称作线程本地变量二、ThreadLocal的调用链浅分析...
2022-04-26 16:03:15
337
原创 40.组合总数II
组合是典型的求一个数列的子集问题,题目中的限制是找出的数列不能重复,那么这个也很简单,只需要将原序列进行升序排序即可,在回溯树横向扩展的时候(for循环),将重复的元素直接跳过即可(不进行递归,具体看代码)
2022-04-21 22:32:51
164
原创 LeetCode46-全排列
LeetCode46-全排列一、题目描述二、回溯树常见的排列问题的回溯树一般有两种写法,下面给出了相应的图示:2.1 基于swap的回溯树树的深度每加深一层,那么该层的每个结点的分支将会减少1,比如第0层是3个分支,到了第1层,每个结点就只有两个分支2.2 基于visited数组的回溯树每一层依然是扩展三个结点,但是重复的结点将会被剪枝,这样也会得到排列问题的回溯树三、代码实现3.1 基于swap回溯树的代码class Solution { public Lis
2022-04-21 22:14:31
137
原创 二叉树遍历系列02-Morris遍历
二叉树遍历系列02-Morris遍历一、引言Morris遍历是一种时间复杂度为O(N),空间复杂度为O(1)的二叉树遍历方法,Morris遍历是一种迭代遍历,Morris遍历不需要借助额外的栈空间,只需要进行普通的循环迭代即可完成整棵二叉树的遍历,因为Morris通过利用结点空指针,完成了遍历的转移(十分巧妙的想法)二、递归序在二叉树遍历系列01,中讲解了二叉树遍历的递归序,这是一个非常重要的概念,因为这可以帮助我们更好的理解Morris遍历在遍历过程中对先序序列和中序序列以及后序序列的加工(
2022-04-20 18:38:15
826
2
原创 二叉树遍历系列01-递归遍历与递归序
二叉树遍历系列01-递归遍历与递归序一、引言先序遍历先序遍历又名先根遍历,顾名思义,在这种遍历方法中,首先遍历根结点,然后再先序遍历根节点的左孩子,之后先序遍历根节点的右孩子,从这个遍历规则中,我们可以看出,有很明显的递归意味,因此使用递归方法实现树的先序遍历是一种常见的方法,非常简单中序遍历中序遍历,和先序遍历不同的是,中序遍历并不是先访问根节点,中序遍历先访问根节点的左孩子,然后访问根节点,最后访问根节点的右孩子,这个中的意思也就很明显了,就是把根节点的遍历放在左孩子和右孩子的中
2022-04-20 16:33:29
299
原创 一个伸展树的实现
伸展树实现(java语言版本)一、伸展树的基本概念伸展树是一种二叉搜索树,伸展树也是一种平衡树,不过伸展树并不像AVL树那样对树的平衡有很严格的要求(左右孩子高度之差不能超过1),伸展树通过一系列的伸展操作,可以保证对伸展树的任意连续M次操作,其时间复杂度不会超过MlogN级别,并且伸展树的实现相较于AVL树也简单了很多,不论是插入还是删除算法二、伸展树的伸展操作伸展树之所以能够保证MlogN的界,就是因为伸展树的伸展操作,每一次调用伸展树的search方法查找一个结点的时候,如果存在,那么就
2022-04-20 09:53:25
529
原创 回溯算法之子集问题
回溯算法之子集问题一、回溯算法简介回溯算法是一种穷举算法,因此回溯算法是一种暴力求解的算法,它的时间复杂度可以达到O(N!),但是有些问题我们通过暴力枚举的方式来求解显得更简单,比如经典的子集问题和排列问题二、回溯算法与树的遍历其实回溯算法本质上就是在遍历一棵树,这棵树和我们常见的二叉树不同,这棵树可以是多叉的,一般来说解决回溯问题可以分为两个步骤进行:(1)构造回溯树结构,回溯算法本质上就是在对这棵回溯树进行先序遍历(2)编写树的递归版本的先序遍历三、子集问题3.1 子集问题简介
2022-04-16 18:33:18
1306
原创 平衡二叉树(AVL)分析与实现
一、平衡二叉树的简介平衡二叉树的缩写为AVL树,它是一种高度平衡的二叉搜索树,对于平衡二叉树来说,它满足两个基本约束:(1)二叉搜索树的约束:对于任意一个节点,左子树的关键字都小于根节点,右子树的关键字都大于根节点(2)平衡性约束:对于任意一个节点,左右孩子的高度之差的绝对值不超过11.1 相关概念高度平衡二叉树的高度定义和普通树的高度定义相同:树的中某个节点高度定义为:从该节点出发,到其可达的最远的那个叶子节点的路径中的边数。空节点的高度定义为-1,叶子节点的高度定义为0平衡因子
2022-04-15 19:48:19
852
原创 二叉查找树的递归实现(基于java语言)
二叉查找树的递归实现一、基本概念二叉查找树是一种特殊的二叉树,特殊就特殊在它的节点的值上,在二叉查找树中任意一个节点的左孩子的关键字,一定小于根节点,右孩子的关键字一定大于根节点二、二叉查找树的基本操作2.1 插入如果根节点为空,那么新插入的节点就是根节点如果根节点不为空,那么让cur指向根节点root,其中cur表示当前正在访问的节点。不妨设新插入的关键字是key,比较cur.key和key的大小,如果key更大,那么让cur=cur.right(因为当前新插入的关键字更大,所以key
2022-04-13 16:27:08
973
原创 随笔练习+表达式树简单实现+二叉树的Morris遍历(先中后)+先序和中序重构二叉树
随笔练习import java.util.Stack;/** * @author 西城风雨楼 */public class ExpressionTree { private TreeNode root; private ExpressionTree() { } /** * 从后缀表达式构建一棵表达式树 * * @param suffix 后缀表达式 * @return 返回构建完毕的表达式树 */ pu
2022-04-12 19:00:44
484
原创 一种好玩的链表遍历方法
一种链表遍历方法(printLots)printLots遍历简介:给定两个链表,list = [1, 2, 3, 4, 5, 6],slots = [1, 2, 4]其中list是待遍历的链表,slots中的元素表示的是一组位置元素,我们需要实现一种打印方式,打印list中指定位置的元素,而这些位置由slots指定,比如本例中,slots链表中的元素1,表示要输出list中位置1处的元素,也就是2,依此类推。c语言简单实现:#include <stdio.h>#include &
2022-04-09 21:50:15
1582
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人