自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(61)
  • 收藏
  • 关注

原创 模板方法模式

这里的“算法”,我们可以理解为广义上的“业务逻辑”,并不特指数据结构和算法中的“算法”。这里的算法骨架就是“模板”,包含算法骨架的方法就是“模板方法”,这也是模板方法模式名字的由来。下面是一个简单的Java示例,展示了如何使用模板方法设计模式:

2024-04-28 08:00:00 218

原创 观察者模式

观察者模式是一种行为设计模式,允许对象间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖它的对象都会得到通知并自动更新。在这种模式中,发生状态改变的对象被称为“主题”(Subject),依赖它的对象被称为“观察者”(Observer)。观察者模式(Observer Design Pattern)也被称为发布订阅模式让我们通过一个简单的例子来实现观察者模式。假设我们有一个气象站(WeatherStation),需要向许多不同的显示设备(如手机App、网站、电子屏幕等)提供实时天气数据。

2024-04-27 09:29:07 990

原创 适配器模式

适配器模式的主要目的是在不修改现有代码的情况下,使不兼容的接口能够协同工作。通过引入适配器角色,客户端可以使用目标接口与需要适配的类进行通信,从而实现解耦和扩展性。使用继承实现适配器功能,适配器类继承了原有的类(Adaptee)并实现了目标接口(Target)。适配器设计模式(Adapter Design Pattern)是一种结构型设计模式,用于。,使得它们可以协同工作。在实际开发中,应根据具体需求选择使用类适配器还是对象适配器。

2024-04-26 18:32:01 179

原创 装饰器模式

就比如说上面的例子,BufferInputStream包装了一个FileInputStream,对原始对象进行了增强,而且装饰器模式支持层层包装。我们会经常使用原始类,也经常使用包装类,使用方式更灵活了,装饰器模式可以让原来功能不够强大的对象逐渐变强。比如说,我们给service层中的每个方法的特定位置加上日志,日志本身与我们的业务逻辑并不是强相关的,而且我们之后也一般不会使用到原始对象了,而是直接面向代理开发,使用代理中的方法,代理模式的初衷是屏蔽原始对象并增强功能。

2024-04-25 10:41:28 840 1

原创 建造者模式

如果构造函数参数过多,我们就需要考虑使用建造者模式,先设置建造者的变量,然后再一次性地创建对象,让对象一直处于有效状态。比如我们定义了一个长方形类,如果不使用建造者模式,采用先创建后 set 的方式,那就会导致在第一个 set 之后,对象处于无效状态。实际上,如果我们并不是很关心对象是否有短暂的无效状态,也不是太在意对象是否是可变的。比如,对象只是用来映射数据库读出来的数据,那我们。的构造函数是私有的,外部无法直接创建该类的实例。而且,使用建造者模式来构建对象,代码实际上是有点重复的。

2024-04-24 09:00:00 266

原创 工厂设计模式

一般情况下,工厂模式分为三种更加细分的类型:简单工厂、工厂方法和抽象工厂。

2024-04-23 10:46:29 470

原创 单例设计模式

单例设计模式(Singleton Design Pattern)理解起来非常简单。一个类只允许创建一个对象(或者实例),那这个类就是一个单例类,这种设计模式就叫作单例设计模式,简称单例模式。

2024-04-21 10:47:22 604

原创 Java基础---反射

反射允许对成员变量,成员方法和构造方法的信息进行编程访问。这么说可能比较抽象,可以简单理解为:反射就是一个人,可以把类里面的成员变量,成员方法,构造方法都获取出来。并且可以获取到成员变量、构造方法、成员方法的所有信息。对于成员变量:我们可以获取到它的①修饰符 ②属性名称 ③类型 ④ 获取变量值/赋值对于构造方法:可以获取到①修饰符 ②形参 ③方法名 ,甚至还可以利用获取出来的方法创建对象。对于成员方法:可以获取到。

2024-03-19 21:38:36 584

原创 jenkins插件下载失败bug

Jenkins > Manage Jenkins > Plugin Manager、点击Advanced页面替换Update Site的url、并submit。如果遇到安装jenkins插件经常失败并报以下类似错误,很可能是因为jenkins国外官方插件地址下载速度非常慢,我们可以修改为国内插件地址。选项,这意味着对文件进行原地编辑,即直接修改文件内容,而不是输出到标准输出。将国外官方地址替换为国内清华大学jenkins插件地址。最后重启Jenkins就应该可以了。字符串,并将其替换为。

2024-02-29 21:44:08 1492

原创 买卖股票的最佳时机 II

某一天买入股票,未来任意一天卖出,只能卖了再买,但可以买卖多次,并允许同一天卖出后再买入,求最大利润。先定义两个指针i ,j ,i表示当前股票的价格, j表示下一天股票价格,只要有利润就记录。因为要保证利润最大,只能逢涨就买入,遇跌不买。有利润就买卖,只看眼前。

2024-02-28 15:23:03 415

原创 买卖股票的最佳时机

这时发现股票有涨幅,但不一定第 j 天卖出的利润最大,还需观察,先把第j天卖出的利润记录下来,接着 i 不变, j++,题目说了,某一天买入股票,未来任意一天卖出,只卖一次,求最大利润,i 尝试买入,j 尝试卖出。我们能发现一个规律:当遇到涨时,i不变,j++, 遇到跌时,i 变为 j, j++此时到第j天卖出仍有涨,所以i不变,j++,一直找到最大利润。

2024-02-26 09:41:36 330

原创 设计推特(Leetcode355)

同样,一个用户可以发送多条文章,用户和文章也是一对多的关系,因为题目有一个方法,获取一个用户发送的近10条文章(其中包括关注者发送的),我们可以用一个链表来存储推文,在用户类中设置一个头节点。这里面有个方法getNewsFeed()获取最新的10篇文章, 包括自己发送的和关注者发送的,其实这就是一个多链表合并问题,按推文时间合并,可以采用大顶堆的方式把自己的推文和关注者的推文加入堆中,然后从堆中弹出一个最近的文章,然后再加入该链表的下一篇推文。推特其实类似于微博,在微博中可以发送文章。

2024-02-25 20:54:44 805

原创 Leetcode535(设计短网址)

题目要求可以将一个长网址变成一个短网址(encode),也可以通过短网址找到原来的长网址,我们可以使用两个hashMap集合来实现。longToShort 和 shortToLong 两个集合。longToShort集合 的key为 长网址, value为生成的短网址, 同时往shortToLong集合中加入key为短网址,value为原来的长网址。上一种方法要考虑生成的短网址冲突问题, 为了简化判断,可以用递增数来实现。

2024-02-22 22:33:51 480

原创 Leetcode155(设计最小栈)

当向栈中加入数据时,比如先加入元素 2 , 在A栈中直接存入 2, 同时新加入元素与 B栈的栈顶元素比较,把较小值加入B栈。保证在每次加入元素后,B栈的栈顶是本次的最小元素。其实和第一种方法思路差不多,我们可以把新添加元素和栈里面的最小元素一起加入栈中,这样我们可以少用一个栈的空间。要存储这样的数据我们可以使用一种特殊的数据类型, --> record ,它是JDK16引用的新语法,刚开始, A栈没有数据, B栈先储存一个元素MAX(整数最大值)。当弹出元素时,A栈正常弹出元素,同时B栈也要弹出元素。

2024-02-21 20:45:45 517

原创 Leetcode1206(设计跳表)

这段代码根据 curr.next[level].value < val 这个条件,我们最后找到的节点是目标节点的前一个节点,当然目标节点也可能不存在。①:跳表中的元素已经是排好序的(图中从小到大),而链表中的元素对顺序没有要求,可以乱序。②:创建新节点随机高度,高度尽可能小(如果跳表的每个节点都很高,那么查询效率就低了)注意:这里向下找的条件 和 向右找的条件是互斥的,所以不用再写一个向下找的判断逻辑。③:修改新节点的next指针 和 路径节点的next指针。我们先来找一找跳表与单链表的相同点和不同点。

2024-02-20 22:36:25 435

原创 SpringAop是什么?

AOP:Aspect Oriented Programming (面向切面编程、面向方面编程),其实就是面向特定方法编程。

2024-02-19 15:36:15 1066

原创 LFU缓存(Leetcode460)

这道题可以用两个哈希表来实现,一个hash表(kvMap)用来存储节点,另一个hash表(freqMap)用来存储双向链表,链表的头节点代表最近使用的元素,离头节点越远的节点代表最近最少使用的节点。put方法分为两种情况:如果要添加的key不存在,说明是新元素,放到key为1的位置上,如果key存在,此时是修改操作,改变元素的value值,对应的频次+1,同样放到对应的位置上。这是kvMap: 它的key没有什么特殊含义,value是储存的节点。注意:freqMap 的 key 为节点的使用频次。

2024-02-04 22:21:39 549 1

原创 LRU缓存(Leetcode146)

我们可以用双向链表来储存数据(key-value),当调用put方法添加数据时,可以将数据(key-value)添加到双向链表的队头,队头的元素表示最新使用的元素,越靠近队尾,就是最久未用的元素。题目要求函数get和put要达到O(1)的时间复杂度,可以用 hashMap 来实现,因为要满足。当调用get方法时,若存在此元素,则从双向链表中把该组数据(key-value)提到队头来。的一个效果,还需要配合一个双向链表来共同实现。链表中的节点为一组key-value。

2024-01-31 22:38:06 906

原创 最小覆盖子串(Leetcode76)

先定义两个变量i,j,一开始,i 和 j 都指向原始字符串的0索引处,看看此时 i ~ j 范围内的字符串是否满足目标字符串(t),如果不满足,则 j 指针往后移动(j++),i 指针先不动,扩大 i ~ j 的范围,直至i ~ j 范围内的字符串满足目标字符串(t),此时记录i 和 j 的位置。然后 j 指针不动,i++,在满足目标字符串的情况下不断缩小范围,找到最小覆盖子串。2.如果原始串 i ~ j 范围内不满足条件,j++ 扩大范围,直到满足条件 j 停下来。

2024-01-25 21:40:47 632

原创 最长回文子串(Leetcode5)

寻找最长回文子串,简单说就是以一个字符为中心点,由中心点向两边扩散,如果两边的字符相等,则继续扩散,直至两端的字符不相等,此时就找到了最长回文子串的左右边界(left,right)。根据数组的遍历顺序,一开始以字符b为中心点,并记录此时回文子串的长度,如果后续找到了更长的回文子串,则替换之前的长度。但这样显然不行,因为b、c不一样,必须找到两个一样的字符作为中心点。注意:以两个字符作为中心点的时候,i不要遍历到数组末尾元素,否则会索引越界。但是在这里我们还遗漏了一种情况,我们只考虑了中心字符为奇数的情况,

2024-01-22 21:32:23 473

原创 最长公共前缀(Leetcode14)

一列一列地进行比较,先比较第一列的字符,若都相同,则 i ++ ,继续比较第二列的字符。直至出现不匹配的字符。j表示数组中的每一个字符串, i 表示每个字符串中的第几个字符。情况2:比较某一列时,遇到字符串长度不够,i 之前的字符就是解。情况1:比较某一列时,遇到不同字符, i 之前的字符就是解。情况3:i 循环自然结束,此时第一个字符串就是解。这样比较会出现以下3种情况,需要分开处理。我们可以都用第一个字符串作为返回的模板。我们可以先定义两个变量 i , j,

2024-01-20 22:01:48 439

原创 找出字符串中第一个匹配项的下标(Leetcode28)

先给出一个字符串pattern,要拿着pattern字符串和原始字符串(origin)比对,若在origin中找到了pattern字符串,则返回pattern字符串在原始字符串origin中的下标。注意:外层循环不必循环origin.length 次,循环origin.length - pattern.length 次即可。可以使用两个循环来依次比对,外层循环表示从原始字符串索引 i 开始和pattern进行比对,先拿着pattern和origin从第一个字符开始依次比对。

2024-01-10 21:34:08 483

原创 接雨水(Leetcode42)

②再计算高度:注意右边的柱子right不一定比left高,pop的高度不一定为0,我们应该从right和left中选出高度较小的(min),Math.min(right, left), 然后再用(min的高度 - pop的高度)与上面计算的宽相乘就能得出雨水的容量。图中左边表示栈底,当新加入的元素(right)比栈顶大时,先把栈顶元素弹出,被弹出的元素记为pop,此时需要检查pop的左边是否还有元素,若有元素表示存在凹陷,应该计算雨水容量。因为5比2、3、4都要大,要把这三个元素先弹出栈,再加入元素5。

2024-01-09 10:09:28 461

原创 滑动窗口最大值(力扣239题)

如果把上图中的数字 -4 改为 1,当往队列加入1时,会把前面的-1,-3覆盖掉,此时队列长度小于滑动窗口值,用单调递减队列找到的最大值(数字3) 其实是过期的。我们可以使用单调递减队列来找到滑动窗口中的最大值,每次向单调递减队列加入元素,队列的队头元素就是滑动窗口里面的最大值。这里可以利用索引,当遍历到第 i 个索引时,i - k 处的元素就是过期的元素,应该移除。如果向单调递减队列中加入数字 1,可以直接加入,不会改变队列中递减的要求。当队列中的元素超过滑动窗口的范围( k ),要及时把队头元素移除。

2024-01-03 23:22:51 437

原创 盛最多水的容器(力扣11题)

我们可以先固定第一个挡板( i )和最后一个挡板( j ), height[0] = 1, height[8] = 7,看看盛水量。我们发现,固定了两个挡板,当移动高的挡板时,盛水量随着 j 指针的左移在不断减少,必然小于最初的盛水量,因此我们不能移动高挡板。这道题给出了一个数组,数组里的元素可以看成每一个挡板,要找到哪两个挡板之间盛的水最多,返回盛水量的最大值。现在盛水量比较少,要让盛水量尽可能多,假设我们先移动 j 指针。移动较低的挡板,盛水量是有可能增多的。这其实是一个双指针问题。

2023-12-30 11:40:34 397

原创 Leetcode15 - 三数之和

这道题可以用之前两数之和的解法。三数之和,我们可以先固定一个数,比如先固定 -4,那么接下来我们要找的两个数之和等于 +4就行了,看看能不能找到解,然后再固定其他的数。固定 -1, 0,1,2(重复的元素不用固定)给定了一个数组,先排好序:nums = [ -4, -1, -1, 0, 1, 2], 题目要求返回。此图中已经固定了 - 4,接下来找剩下两数之和等于target = 4 就可以了。注意:运用之前两数之和的解法需要数组先排好序。其实这道题类似于力扣的40题组合的题目。

2023-12-21 11:57:52 329

原创 Leetcode167 - 两数之和Ⅱ

用双指针的思想,定义两个指针i,j,i指向数组中的第一个元素,j指向数组中的最后一个元素。把指针i,j所指向的两个元素相加和target比较。蓝色的线代表target,黑色的线分别表示数组中已排好序的元素。i + j 和 j + i 的结果图中都画出来了(看哪根线都一样)..... 重复上述过程,直到找到和为target的两个元素。①:两个指针 i 和 j 分别指向最左侧和最右侧的数字。不难发现,i + j 的结果大于 target,因此。,让i + j的和变小一点。先把i处和j处的元素相加。

2023-12-20 19:01:27 41

原创 解数独 - 回溯

③:先在表中找到空方格,然后向空方格填入数字,逐一尝试1~9(检查要填入的数字是否冲突),填入成功后记录填入数字后的冲突,如果1~9都不能填,则回溯到上一次的状态,重新填。我们需要记录表格内每一行是否有冲突,每一行又有9个数字,需要知道这9个数字是否被使用过,被使用过的数字记为true,因此可以创建一个boolean型的二维数组来记录冲突。接着创建九宫格冲突状态:需要找到每个小方格和九宫格的对应关系,i 表示二维表格的行,j 表示二维表格的列,2、一旦1~9 都尝试失败,回溯到上一次状态,换数字填入。

2023-12-19 20:59:20 29

原创 N皇后问题 - 回溯

按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。n皇后问题研究的是如何将n个皇后放置在 n x n 的棋盘上,并且使皇后彼此之间不能互相攻击。

2023-12-17 13:36:15 96

原创 Leetcode40 - 组合总和Ⅱ(回溯)

其实这题的解法和Leetcode39题解法类似,上面给定的集合【10,1,2,7,6,1,5】中,1有两个,我们可以把它们看成之前的1 和 1', 规定1' 只能出现在 1 之后,否则无效。注意:题目中说了每个数字在每个组合中只能使用一次,而且解集不能包含重复的组合。

2023-12-13 20:12:13 25

原创 Leetcode39 - 组合之和

假如现在有一个数组candidates = [2, 3, 6, 7],需要组合和为7(target = 7),我们可以先固定2,此时 target = 7 - 2 = 5, 还不够,要继续组合,继续从数组的开始(第一个元素2)进行组合,因为数组中的元素可以被重复选取。再固定2,2, target = 3,固定2,2,2,target = 1,再固定2,2,2,2,此时 target = -1 < 0,不满足条件,要回溯到2,2,2。接着和3,6,7组合(保不齐数组中有个元素1)。图中蓝色的矩形表示有效解。

2023-12-13 18:50:01 25

原创 组合 - Leetcode77

我们可以采用之前全排列的思想,先固定1,然后找有效的组合数(12,13,14),回溯, 再固定2,找到23,24, .... 固定4时,因为后面已经没有其他的数与4组合,因此单独的4为无效组合。如果 n = 4,k = 3,假设现在处理的是数字 1 (还没有把1加入栈里),现在栈中还缺3个元素满,而现在的备用元素是 1,2,3,4。假如 n = 4, k = 2, 表示在 1 ~ 4 中随意找两个数组合,返回所有可能的组合,不能重复。组合有 1 2 ,1 3, 1 4,2 3, 2 4, 3 4。

2023-12-12 19:37:28 67

原创 全排列(含有重复数字) - 回溯

我们可以先给含有重复数字的序列排序,使数组中的相同元素相邻,这时可以把 第二个 1 看成 1',规定 1 必须排在 1' 之前。1' 排在 1之前的情况不合理,直接跳过。假如要给[1, 1, 3 ] 进行全排列,不能排列重复。

2023-12-11 19:35:20 81

原创 全排列-回溯

程序在运行过程中分成了多个阶段。通过某些手段,将数据恢复到之前某一阶段,这就称之为回溯。手段包括: ①方法栈 ②自定义栈比如给数字1, 2, 3进行全排列。我们可以先固定数字1, 对2,3进行排列;然后固定2,对1,3进行排列;最后固定3,对1,2进行排列。在代码实现时,我们需要准备两个数组,一个代表原始数组【1,2,3】,另一个数组,用来表示数字是否已固定(被使用过),已固定用灰色表示,未固定绿色表示。是个boolean变量。

2023-12-10 20:43:47 30

原创 至少 k 个字符的最长子串

题目要求子串中的每一字符出现次数都不能少于k, k 在参数中给出,举个栗子: 字符串 "aaabb",这时 k = 3,它的最长子串为 "aaa"。同理,在字符串"ababbc"中,c字符只出现了1次,题目要求子串中每一字符出现两次,因此最长子串只能是"ababb"。因为 k = 3,我们需要把原始字符串中字符出现次数小于3的字符剔除掉,其中x出现一次,c出现两次,e出现一次,将来组合子串的时候,谁带上它们谁倒霉~核心思想:统计字符串中每个字符的出现次数,移除那些出现次数 < k 的字符,

2023-12-09 20:38:15 30

原创 MySQL - 索引

索引(index)是帮助MySQL高效获取数据的数据结构(有序)。在数据之外,数据库系统还维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据,这样就可以在这些数据结构上实现高级查找算法,这种数据结构就是索引。假如我们要执行一条SQL语句为: select * from user where age = 18;在无索引情况下,就需要从第一行开始扫描,一直扫描到最后一行,我们称之为 全表扫描,性能很低。

2023-12-06 21:10:36 28

原创 平方根整数部分

我们还是同样求99的平方根,可以求 1 到 99之间的中间值,是(1+99)/ 2 = 50,然后算出50的平方, 50 x 50 = 2500,远比99大, 继续缩小范围求中间值,这次是 1 到 49 之间,(1 + 49)/ 2 = 25,25 x 25 = 625 > 99,还是比99大,继续缩小范围,以此类推。因为9的平方是81(9x9=81),比99小,10的平方是100(10x10=100),比99大,因此99的平方根肯定介于9 ~ 10 之间,为 9.?所以,99的平方根整数部分是9。

2023-12-06 20:02:31 66

原创 快速幂 - 分治

介绍快速幂之前我们先来看一道例题。

2023-12-05 21:12:43 39

原创 Divide and Conquer(分治)

分治思想:①将大问题划分为两个到多个子问题。②子问题可以继续拆分成更小的问题,直到能够简单求解。③如果有必要,将子问题的解进行合并,得到原始问题的解。其实我们之前有学过带有分治思想的一些算法,比如二分查找,二分查找就是将一个大问题拆分为两个子问题,在子问题中求解。还有快速排序算法,选定基准点后分区。还有归并排序等等。。。分治和动态规划有点相似,他们求解时都需要拆分子问题,但是动态规划的子问题有重叠,因此需要记录之前子问题的解,避免重复运算。然而分治的问题没有重叠。

2023-12-04 20:08:06 35

原创 旅行商问题(笔记)

现在假设有4个城市,到各个城市都有一定的花费,你是一个旅行商要到这4个城市去售卖物品,这4个城市必须都走一遍,问走哪条路线花费最少?(起点可任意,最终要回到起点)

2023-12-03 18:05:53 150

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除