自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+

每天努力Coding

一步一个脚印

  • 博客(107)
  • 收藏
  • 关注

原创 RocketMQ知识点总结

IndexFile(索引文件)提供了一种可以通过key或时间区间来查询消息的方法。Index文件的存储位置是: {fileName},文件名fileName是以创建时的时间戳命名的,固定的单个IndexFile文件大小约为400M,一个IndexFile可以保存 2000W个索引,IndexFile的底层存储设计为在文件系统中实现HashMap结构,故RocketMQ的索引文件其底层实现为hash索引。

2024-04-14 21:40:51 855

原创 HashMap扩容源码探究——高低链表的判断过程

我们发现,变化的其实只有第一个1所在的位置,数组长度是2的倍数,而和旧的运算的区别其实就是前面有没有多一个1,我们只需要知道hash的该位置有没有1即可。具体来说,其实就是oldCap化成二进制的那个1所在位置,newCap就是oldCap的1前移了,那么就会导致-1之后&运算之后多了一个1。于是乎,我们也得到了为什么要分高位和地位了,其实就是二进制多了一个1,这个1如果&生效了,其实就相当于在原来的hash基础上+oldCap。链表和红黑树一样,都需要拆成高位和低位,然后移动。在正式看里面运算之前。

2024-04-03 10:53:08 316

原创 MySQL日志探索——redo log和bin log的刷盘时机详解

在双1的基础上,如果我们把sync_binlog改了呢?此时事务提交只需要0.00sec,可以判定提交的瞬间未刷盘,但是提交成功了。因为sync_binlog=N,在后续的1~N-1的事务,commit都是很快,第N个事务commit所消耗的时间是1s左右。也就是在第N次时候,进行了刷盘。这时候有人疑惑了,那么我的组提交参数有啥用?

2024-03-30 20:28:28 1078 1

原创 G1垃圾回收器深入探索——卡表、记忆集和SATB算法

G1的RSet是在Card Table的基础上实现的:每个Region会记录下别的Region有指向自己的指针,并标记这些指针分别在哪些Card的范围内。在GC的时候,对于old->young和old->old的跨代对象引用,不需要扫描整个堆找到谁引用了当前分区中的对象,只要扫描对应的CSet中的RSet即可。在并发标记阶段如果有引用关系被删除,就记录下来,Remark阶段对这些引用关系被删除的重标记,这个破坏了步骤一,即灰色对象断开了白色对象引用的时候,记录下来,后面重新把这个白色对象标记成存活对象。

2024-03-23 20:16:20 907

原创 Morris法解决二叉树问题,展开链表及中序遍历

咋一看非常简单的两道题,但是如果我们加以一些限制,这两题就不简单了。对于这两道题,我们的空间复杂度都必须控制在O(1)。也就是说,迭代和递归全部失效了,这怎么办呢?找到一个节点的前驱节点,然后全部拼接到原来的右边,原来的右边节点直接拼到前驱节点的右边即可。就是将叶子节点指向他的后驱节点。就是阉割版的线索二叉树啊。这样子我们就不需要通过栈来进行存储节点。Morris算法 Morris 遍历算法是另一种遍历二叉树的方法,它能将非递归的中序遍历空间复杂度降为 O(1)。于是我们的主角Morris就出现了。

2024-03-18 19:16:54 186

原创 排序链表的三种写法

第三种,归并排序,主要就是分为归并和合并两部分。拆分时候,通过快慢指针拆出来两个链表头。第二种,推荐面试直接写,堆排序,借助优先队列,能5分钟秒了。第一种,插入排序,会超时。

2024-03-15 16:05:35 211

原创 环形链表的起点——细节讲解

也就是说我们把一个节点放头部重新遍历,再次相交的点就是入环处。对于一个环形链表,我们要找到他的起点。首先快慢指针不能岔开设置,不然推导的T不一样了。到起点的距离是T,圈长是C,第一次相交的点是X。最后要记得特判fast的下一个节点是否存在。其次一开始就要移动,不然一开始指针一样了。我们设置两个快慢指针,相遇的点为X.然后快指针相遇后只能一步一步移动了。化出来T=N*C-X。

2024-03-14 18:04:58 227

原创 最长回文子串超级简单的做法——两次中心扩散

每次进入循环,指针设置一下两边扩散的地点。奇偶指针设置区分一下就行。常见的三种做法分别是动态规划,马拉车和中心扩散。我们分奇偶串进行中心扩散就能找到最长的回文串啦。

2024-03-12 15:29:29 213

原创 Redis的持久化——深入探究底层原理

RDB有两种数据同步方式,一种是save,一种是bgsave,save同步的话,会直接阻塞我们的主线程。这时候也会有一个问题就是如果老倒霉蛋出现了所有的数据都更新了,那么所有的数据都被复制了一份,导致Redis内存翻了一倍。AOF会将命令写入到aof的缓冲区,和mysql的日志写入非常像,我们写入到缓存然后调用系统函数写入内核缓冲区,然后由内核发起操作调用IO写入到硬盘。

2024-03-12 11:20:50 551

原创 手撕经典数据结构——堆

在操作过程中我们需要用到查看父亲节点函数,查看左孩子节点函数,查看右孩子节点函数和交换元素位置函数。除了上面之外,插入和删除两个操作需要涉及到堆的元素上浮函数和元素下沉函数。我们需要定义一个数组,int类型长度和int类型容量。堆的函数主要有,插入,删除,查看堆顶元素。建堆主要依靠插入函数。

2024-03-02 20:56:35 307

原创 MySQL知识点归纳总结(二)

两个事务都对同一个范围加间隙锁,然后尝试插入导致死锁。binlog 文件是记录了所有数据库表结构变更和表数据修改的日志,不会记录查询类的操作,比如 SELECT 和 SHOW 操作。binlog 是追加写,写满一个文件,就创建一个新的文件继续写,不会覆盖以前的日志,保存的是全量的日志。redo log 是循环写,日志空间大小是固定,全部写满就从头开始,保存未被刷入磁盘的脏页日志。binlog 用于备份恢复、主从复制;redo log 用于掉电等故障恢复。

2024-03-02 09:48:11 988

原创 手撕LRU缓存——LinkedHashMap简易源码

首先我们要知道什么是LRU就是最小使用淘汰。怎么淘汰,链表尾部就是最不常用的直接删除,最近使用过的就移动到链表头部。要查找就利用hash表进行映射查找。原理非常简单,一个双端链表配上一个hash表。

2024-02-29 20:07:58 589

原创 手撕Java集合之简易版Deque(LinkedList)

简易版的双端队列实现。

2024-02-28 17:01:09 454

原创 MySQL知识点归纳总结(一)

select的数据列只用从索引中就能够取得,不需要回表进行二次查询,换句话说查询列要被所使用的索 引覆盖。对于innodb表的二级索引,如果索引能覆盖到查询的列,那么就可以避免对主键索引的二次查 询。不是所有类型的索引都可以成为覆盖索引。覆盖索引要存储索引列的值,而哈希索引、全文索引不存储 索引列的值,所以MySQL只能使用b+树索引做覆盖索引。对于使用了覆盖索引的查询,在查询前面使用explain,输出的extra列会显示为 using index。

2024-02-27 20:00:47 1509 1

原创 经典单调栈问题——接雨水

从左到右遍历数组,遍历到下标 i 时,发现不满足单调递减。这时候要保证栈内有两个元素,一个作为中间的间隔标识,一个作为左边的支点。这时候先弹出来一个,然后记录下一个栈顶。这时候可以接的雨水为长*宽(左右两端的距离×左边支点和右边支点最小值和弹出来节点的差)。维护一个单调栈,单调栈存储的是下标,满足从栈底到栈顶的下标对应的数组 height 中的元素递减。

2024-02-27 10:18:10 169

原创 Java并发编程——伪共享和缓存行问题

由于处理器缓存行的一致性协议要求缓存行中的数据在多个处理器间保持一致,因此当一个线程修改了一个变量并使得缓存行失效后,其他线程即使是访问其他变量也会受到影响。这种情况下,就会出现伪共享。当一个线程访问内存时,会将数据从主内存加载到缓存行中,并且在后续的操作中,只对缓存行进行读写,而不是直接访问主内存。然而,当多个线程同时访问同一个缓存行中的不同变量时,由于缓存行的一致性要求,会导致其他线程的缓存行失效,从而降低性能。填充是在变量之间插入一些无意义的字节,使得不同变量分布在不同的缓存行中,从而避免线程冲突。

2024-01-11 20:06:15 735

原创 RocketMQ实现延迟队列

RocketMQ还拥有一些高级特性,例如消息的可靠性投递、消息的顺序性、消息的事务性等。RocketMQ的延迟队列是通过消息的延迟级别来实现的。延迟级别是指消息从发送到被消费之间的时间间隔,可以设置为任意时间段,单位为毫秒。然后创建消息,并设置了延迟级别为2。通过这种方式,可以实现消息的延迟投递,即消息将在指定的延迟时间后才会被消费者消费。在消费者端,可以监听指定的延迟级别来消费延迟消息。请注意,延迟队列只对那些配置了延迟级别的消息生效。构成了延迟级别,它是一个枚举类型,定义了多个级别,例如。

2024-01-09 13:04:20 686

原创 CAS的“ABA”问题

这样,CAS操作在比较并交换值时还会比较版本号或时间戳,从而能够判断出是否存在ABA问题。一种常见的解决方案是使用带有标记位的指针,将标记位用于标记指针所指向的数据是否经历了变化。需要注意的是,解决ABA问题需要根据具体的编程语言和场景来选择合适的解决方案。ABA问题指的是,在CAS操作期间,其他线程可能修改了共享数据的值两次,即A->B->A,使得CAS操作能够成功,但。CAS(Compare and Swap)是一种常见的并发控制原语,用于解决多线程环境下的数据竞争问题。

2024-01-04 23:45:52 416

原创 synchronized锁的底层原理

在 Java 6 之前,synchronized 锁的实现是重量级锁,使用操作系统的互斥量来实现。在 Java 的内存模型中,每个对象都有一个与之关联的 Monitor 对象,这个 Monitor 对象是用来实现对象的锁机制的。总结起来,synchronized 锁的底层原理是通过对象的 Monitor 锁来实现线程同步,当一个线程获取锁时,会将对象的标志位设置为当前线程的 ID,并将其他线程阻塞,当线程释放锁时,会将标志位清空,并唤醒等待队列中的一个线程继续执行。

2024-01-04 18:16:09 586

原创 Java线程池执行流程及参数详解

handler:当线程池中全部线程都在运行,阻塞队列也满的时候,会将添加的任务执行拒绝策略,JDK 线程池中实现了四种拒绝策略,默认 AbortPolicy,并抛出异常。maximumPoolSize:线程池中的最大线程数量,当核心线程都在运行任务,并且阻塞队列中任务数量已满,此时会创建非核心线程。 corePoolSize:线程池中的核心线程数量,如果没有全局设置池内线程的过期时间,池内会维持此数量线程。

2023-12-28 14:20:50 503

原创 力扣Hot100——柱状图中最大矩形(单调栈)

思路:考虑单调递增栈,如果说我拿到的数字比栈顶来的要小,那么说明了我前面比我高的会被我自身的高度限制,所以前面的矩阵要依次出栈统计出来这个局部的最高高度,然后把目前的高度+前面比我高的宽度压入栈中。这题拿数组去模拟栈效果更加好。

2023-12-28 14:05:50 436

原创 单调栈数组问题——每日温度

思路:维护一个递减栈。由于每一次我们都需要知道后面一个较大的值,那么首先遍历数组,如果数是递减的就不断压栈,如果出现了当前数比栈顶的数大的就说明了——栈里面一定可以有至少一个元素能找到较大数字的下标,把满足条件的全部移出栈并更新答案数组即可。我们考虑优化代码,发现里面有很多冗余的地方,我们发现很多特判完了都只是做了压栈的操作,那么把这一步单独拉出来,把出栈判断就行了。的基本思想是,维护一个栈,栈内的元素从栈底到栈顶保持单调递增或者递减的顺序。回到本题:这题就是经典的单调栈题目。

2023-12-26 14:41:55 362

原创 力扣经典面试题——搜索旋转排序数组及最小值(二分搜索旋转数组系列一次搞定)

先来看这个搜索旋转排序数组:https://leetcode.cn/problems/search-in-rotated-sorted-array/description/?首先我们先尝试着二分看看,如果我们二分,就会出现这种情况,就是二分得到的点,左边右边并不是严格递增,如果一个数小于mid那么可能会导致他不在mid前面而是在mid后面。,我们只需要判断目标在不在那个有序的半边,不在就二分另外半边,怎么判断哪个半边有序,直接首尾看看递不递增就行了。我们要找11,每次我们分割半边判断然后看到底在哪一边。

2023-12-24 20:15:42 666

原创 力扣经典面试题——搜索二维矩阵(两次二分搜索)

具体二分查找的写法可以看我之前的文章:https://blog.csdn.net/qq_45816864/article/details/134752708?思路:先按行二分,再按列进行二分。即先找到对应的行,再找对应的列。

2023-12-24 00:20:55 637

原创 Java经典面试题——手写快速排序和归并排序

注意找哨兵那里内循环的等于号不能漏,不然能出不来循环了,因为如果数值都一样,那么l和r一直保持不变了。,因为归并是先拆后再合并,而快速排序我们需要知道哨兵的位置,所以需要先进行局部排序找到哨兵。题目链接:https://www.luogu.com.cn/problem/P1177。通过对比归并排序和快速排序,我们可以发现,归并排序和快速排序的区别在于。技巧:交换数组中的两个位置。

2023-12-23 23:07:19 494

原创 力扣思维题——寻找重复数

这题的思维难度较大。一种是利用双指针法进行计算环的起点,这种方法在面试里很难说清楚,也很难想到。大致做法就是,定义快慢指针,由于数字都是1-n,一共n+1个所以一定存在环。快慢指针一定会相遇,但是相遇的点并不是重复数字的点,所以再将fast放到起点,每次移动一格,再次和慢指针相遇的时候就是环的起点,两个指针每次都是一样快了。可以用一个具体的例子来理解:如果遍历一遍输入数组,统计小于 等于 4 的元素的个数,如果小于等于 4 的元素的个数 严格 大于 4 ,说明重复的元素一定出现在整数区间 [1…

2023-12-22 18:56:56 689

原创 双指针——找到字符串中的所有字母异位词

双指针,每次都统计出来p长度的滑动窗口里的数字,拿Arrays.equals进行对比,然后滑动一小格,减1加1继续比对即可。

2023-12-19 18:31:58 346

原创 双指针的运用——双数之和II和三数之和

我们考虑这个排序过的数组,首先一个指针在最左,一个在最右。如果这两个数字比目标数字来的要小,那么如果我们左边指针移动了,移动后一定变大了,所以这么移动OK,如果移动的右边左移那么由于排序的原因只会越来越小,所以根据这个规律双指针移动就一定能找到。这题较难,我们需要先定下三个点一个,然后在以这个点为起点,后面数组在定义两个节点,进行两数之和的过程,中间需要考虑重复的情况,加特判循环略过重复的点。

2023-12-13 15:42:11 55

原创 链表TOP难度——排序链表

定义一个头节点节点方便链表连接,while(每两个链表进行合并),进行遍历取到左边一个链表,链表末尾指空,进行遍历取到右边一个链表,链表末尾指空,两个链表合并,头节点连接到这个链表,头节点指向这个链表的尾部。

2023-12-12 10:06:23 74

原创 力扣经典面试题——合并区间

通过重写Comparator的compare方法来自定义排序规则,返回的值看正负。

2023-12-11 23:55:09 96

原创 力扣思维题/经典面试题——下一个排序

字节面试题,非常经典的逻辑思维题。这一位已经比原来的大了,后面不管怎么样,这个排列都会比原来的大,要是这个排列尽可能地小,为什么,仔细想想,后面都是倒序了怎么都不可能变得更加大了。

2023-12-10 16:04:27 420

原创 SPI机制——JDBC实现源码中的一个细节

我们知道,JDBC源码中通过SPI文件打破了双亲委派机制并加载了驱动,中间有一个将接口实现类写入META-INF文件的过程,这个过程中会产生这么一个疑问?类的加载是通过读取了这个文件,那这个文件我平时开发也没写过啊。答案就在Maven,Maven工具在构建时候会自动帮助我们写入。

2023-12-07 23:07:26 77

原创 两种做法——判断是否是二叉搜索树

考虑只有两个节点和一个结点的情况,可以头尾各加一个最大最小值,不用特判了,也可以直接特判1和0。由于测试样例里有最大值,所以INT最大值不够用。非常精妙的区间法,利用区间进行递归。

2023-12-07 16:00:39 150

原创 Java的List中的各种浅拷贝和深拷贝问题

我们知道ArrayList源码里主要用到了两个拷贝函数分别是Arrays.copyOf()和System.arraycopy()这表明temp是指向的list的地址而不是拷贝了完整的一份是浅拷贝,那么我们如何才能让双方互不影响。先来看看基本数据类型。这里参考ArrayList源码里面的拷贝实现过程。再回到List,我们可以使用Collections.copy实现深拷贝。

2023-12-06 15:22:38 554

原创 力扣面试经典150题——Unix简化路径

思路:将串以/分割,判断字符串是…/./其他,进行入栈和出栈,最后留下的就是结果,拼装一下就好了。PS:LinkedList的API。

2023-12-05 23:31:20 205

原创 BFS求树的宽度——结合数组建树思想算距离

比如[1,2,3]可以构成一颗二叉树,1是根节点,2和3是孩子,二者的下标分别是×2和×2+1,这样子不同的节点就有了自己的编号。1、考虑树的宽度一定是在一层上的所以进行BFS,树的BFS不建议直接使用队列,每次add/offer然后poll/remove,这样子层级关系不好显示。我们可以定义两个数组,每次从List里面取出所有的元素,这些元素就是一层上的所有的节点。扩展:字节面试题,Z字形遍历树,利用上面的思想非常简单,只需要一个变量每多一层判断奇数还是偶数,对List正着或者倒着遍历。

2023-12-04 22:57:38 187

原创 Mysql中的正经行锁、间隙锁和临键锁

间隙锁(Gap Lock):间隙锁是指在索引的范围之间的间隙上进行的锁定操作。幻读是指一个事务在前后两次读取同一范围数据时,发现有新的满足条件的数据出现。行锁一般是在修改数据时使用的。临键锁可以锁定某一行的同时,也会锁定这个行的前一个间隙,确保其他事务不能在同一个间隙插入新记录。根据具体的业务需求和数据库设计,开发人员可以选择使用适合的锁定方式来保证数据的正确性和并发性。行锁、间隙锁和临键锁是数据库中的三种不同类型的锁,三者都属于行锁,第一个一般叫他正经的行锁(《Mysql是怎样运行的》一书中的说法)。

2023-12-04 22:49:08 210

原创 中序和前/后序遍历构造二叉树———通用做法

*思路:我们每一次一定可以根据递归确定根节点是哪个,就是前序第一个数,然后找中序遍历这个点,看左子树有几个节点,右子树有几个节点,然后就可以根据节点个数,递归左子树和右子树,当且仅当left>right时结束,由于preorder和inorder对应的所以left>right只需要判断一个符不符合就行了。**8个位置的判断一定要仔细。

2023-12-03 19:43:50 87

原创 二分查找边界问题——排序数组找元素第一次出现和最后一次出现

由于哪怕已经找到了对应的值一样,但是我们要的是边界值,所以nums[mid]=target的时候不能退出循环,依旧要继续下去。同时如果mid值和要找的值相等,不能+1或-1,比如left=mid+1这种,因为如果是边界这个值就丢了。考虑left=5,right=6这种情况,如果5,6的值都是满足的条件的怎么办?如果mid=(left+right+1)/2,那么最后的mid就是6,如果mid=(left+right)/2,那么最后的mid就是5,

2023-12-02 15:16:26 416

原创 二叉树展开为链表的三种写法

新建一个树形链表,前序遍历这个树,遍历到一个节点就往里插;每次找左子树最右的节点,然后连接即可。

2023-12-01 21:33:20 69

空空如也

空空如也

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

TA关注的人

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