自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

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

原创 初探 JUC 并发编程:Java 中的并发队列 ConcurrentLinkedQueue 源码级解析

offer 操作介绍offer 操作是在队列的末尾添加一个元素,由于队列是无界队列,所以一定会返回true;当传入的值为 null 的时候,会抛出 NPE 异常。// e 为空则抛出空指针异常// 构造 node 节点// 从尾节点开始插入;) {// p 的下一个节点为空,说明 p 是最后一个节点// 通过 CAS 操作设置 p 节点的 next// 每插入两个节点的时候会执行这个方法if (p!= t)// 当 p 节点(指向的是尾部节点,发生自旋的的时候)

2024-05-14 14:48:55 798

原创 初探 JUC 并发编程:读写锁 ReentrantReadWriteLock 原理(8000 字源码详解)

然后去判断当前线程是否应该被阻塞,也就是 AQS 队列的队头是不是请求的写锁,然后去判断最后一个获取到锁的线程是不是本线程,如果不是的话,检查线程中的 readHolds 是否为 0(如果为 0 则说明没有获取到锁,如果获取到了锁这里应该置为 1),因为 get 方法会向线程的 ThreadLocal 中添加对象,所以在确定它没有得到锁之后清楚 ThreadLocal 中的内容。

2024-05-10 20:53:06 799

原创 初探 JUC 并发编程:独占锁 ReentrantLock 底层源码解析

`ReentrantLock` 中提供了以上的两种构造方法,其作用和引言中说的相同,即构造公平锁或者非公平锁,`ReentrantLock` 中的内部类 `Sync` 这个类直接继承了 `AQS` ,它的两个子类 `FairSync` 和 `NonfairLock`分别实现了公平锁和非公平锁, `ReentrantLock` 类中的核心方法都是调用这两个子中类的方法来实现的。

2024-05-10 11:44:39 1033

原创 Netty 网络编程深入学习【一】:ByteBuffer 源码解析

ByteBuffer是一个用于处理字节数据的缓冲区类。它是Java NIO 包的一部分,提供了一种高效的方式来处理原始字节数据。ByteBuffer可以用来读取、写入、修改和操作字节数据,它是一种直接操作字节的方式。

2024-05-03 13:35:05 671

原创 初探 JUC 并发编程:Java 并发包中并发 List 源码剖析

并发包中的并发 List 只有。这是一个线程安全的ArrayList,对其进行修改的操作都是在底层的一个复制数组上进行的,也就是使用了写时复制策略。每个/***/上面的注解的含义是这样的:保护所有变化的锁。(我们对内置监控器略有偏好,而不是,两者都可以。这个锁的类型要根据不同的 Java 源码来看,不同的团队会有不同的设计选择,所以如果追源码发现这个锁的实现不同,是因为我们看的源码的版本不同。这里使用的就是独占锁。通过上面源码的阅读,可以发现,

2024-04-29 20:52:57 1363 2

原创 初探 JUC 并发编程:ThreadLocalRandom 原理剖析

ThreadLocalRandom 的继承关系是这样的,它继承了 Random 类并且重写了 nextInt 方法,ThreadLocalRandom 类中使用的种子存放在调用线程的 threadLocalRandomSeed 变量中,当线程调用了 ThreadLocalRandom 类的 current() 方法的时候,ThreadLocalRandom 会去初始化调用线程的 threadLocalRandomSeed 变量,也就是初始化种子。

2024-04-28 21:33:30 985

原创 LeetCode 热题 100 题解:二叉树部分(1 ~ 5)

所谓中序遍历就是按照这个顺序去遍历处理一个**节点,**即 左子树、节点、右子树这样的方式,所以对于一个节点的处理方式就是这样的:遍历它的左子树、记录节点的值、遍历它的右子树对每个节点都要进行上述的操作,而递归解法就可以实现这样的效果,只需要将上面的逻辑想清楚,剩下的交给递归去做就可以了。

2024-04-27 16:04:56 570

原创 LeetCode 热题 100 题解:普通数组部分

其中会有一个极端的情况,假如数组的长度为 N,而数组中的元素恰好就是 1 ~ N 中的所有元素,那此时最小的正数就是 N + 1;那第一个思路就很简单了,首先创造一个新的数组,然后对于原数组先从 length - m 遍历到末尾,然后再遍历 0 到 length - m - 1 这部分的内容,将这些内容填充到新的数组中。如果不考虑 0 的情况下,本题的思路其实是比较容易的,就是先计算出整个数组的乘积,然后遍历到数组中的某个元素的时候,用这个乘积去除以这个元素,得到的结果放到 answer 数组中。

2024-04-18 18:29:35 1035

原创 LeetCode 热题 100 题解(二):双指针部分(2)| 滑动窗口部分(1)

比如上图中的红色部分,它存储水的容量其实就是 **左边的最大高度** 和 **右边的最大高度** 的 最小值,减去这里的格子高度(案例中为 0),在上面的案例中,左边的最高高度为 2,右边的最高高度为 3。所以本题的暴力解法就比较好想了,找到其左边最大高度,再找到其右边的最大高度,通过上面的规律进行运算。

2024-04-10 17:45:07 780

原创 LinkedHashMap 是如何保证返回的顺序性的?

读到这里其实就可以大致了解到 LinkedHashMap 的机制,就是将 HashMap 中的 Node 节点替换为了类中的 Entry,新增了 before 和 after 节点来创造出一个依据顺序连接的双向链表,由此来达到存储插入顺序的目的。首先获取了此时的 last 节点,也就是链表的最后一个元素,然后做了一个判断,如果 last 是空的,就说明此时数组中没有元素,是第一次添加,此时就将 head 也置为 p 节点,否则就将 p 与 last 节点双向连接。

2024-04-10 10:57:44 1030 2

原创 LeetCode 热题 100 题解(二):双指针部分(1)

上面代码展示的就是遍历第一个元素的逻辑,首先要保证 i 不会越界,其次要保证 nums[i] 是小于等于零的,当发现 nums[i] > 0 的时候就说明本次的查找已经结束了,直接将 res 返回;第二段 if 进行去重的,就是如果发现 nums[i] == nums[i - 1] (和上一个相同),此时就直接遍历下一个元素。

2024-04-09 18:16:42 634

原创 万字源码解析!彻底搞懂 HashMap【二】:putVal 方法和 resize 方法(重点)

面试题引入:什么重写equals()方法的同时需要重写hashCode()方法?HashMap 的初始化大小为什么是 16?说一下 HashMap 的扩容。

2024-04-09 13:36:18 1176

原创 万字源码解析!彻底搞懂 HashMap【一】:概念辨析与构造方法源码解析

这里指定的是默认的负载因子的值,为 0.75,负载因子(Load Factor)是指哈希表中已存储元素数量与哈希表容量的比例。在哈希表中,负载因子用于衡量哈希表的填充程度,即已存储元素占哈希表容量的比例。通常情况下,负载因子是一个介于 0 到 1 之间的数值,在哈希表中,当负载因子达到一定阈值时,通常会触发哈希表的扩容操作,以保持哈希表的性能。常见的默认负载因子值为 0.75,这是一个经验值,可以在平衡内存占用和性能之间做出权衡。

2024-04-08 14:35:21 735

原创 LeetCode 热题 100 题解(一):哈希部分

如果说当前遍历到 7,从开头到 7 是否遍历过 2 即可;但是这样每次都要从头开始遍历,时间开销比较大。那能不能通过一个映射关系将每个数据是否出现和出现的位置存储下来,然后通过查询这个映射关系,来快速得知数组中是不是存在这个元素了呢?比如上面的情况,当遍历到 2,先查询前面是否遍历到过 target - 2,如果没有就将 2 存储下来,并且与其出现的位置做一个映射;此时当遍历到 7 的时候,就可以通过查询这个映射来得知 2 是否出现过和其最后一次出现的下标是什么了。

2024-03-29 22:00:56 977

原创 六千字详解!一篇看懂 ArrayList 的扩容机制(完整源码解析)

这是一个共享的(static)空数组实例,被用作使用 默认无参构造方法 时,elementData 的默认值;它的作用是与另一个共享的空数组实例来做区分,那另一个共享数组为 EMPTY_ELEMENTDATA,它在接下来要讲的 有参构造方法 中具有很重要的作用;简单来说 DEFAULTCAPACITY_EMPTY_ELEMENTDATA 是标识着通过无参构造形成的空 ArrayList,而 EMPTY_ELEMENTDATA 是通过有参构造形成的空 ArrayList,它们在后续的扩容策略中会有所不同。

2024-03-29 21:05:03 1230 1

原创 代码随想录刷题笔记 Day 59 | 两个字符串的删除操作 No.583 | 编辑距离 No.72

同时观察到递推公式依赖的是左上角,也就是此时要初始化第一行和第一列:第一行的含义是 长度为 0 的字符串1和字符串2变为相同需要多少次,让一个有长度的单词变为长度为 0,那就只有一种删除操作了,需要的次数是单词的长度次;比如上图的情况,这里发现两个 a 是相同的,此时要想让这两个字符串相同,就需要绿色部分也相同,也就是要加上使得绿色部分相同的操作的次数,这个次数正是。那什么时候能保证两个单词都保留的最多呢?代表将 i - 1 长度的单词 1 和 j - 1 长度的单词 2 变为同一个单词需要的最少的步数。

2024-03-27 14:40:30 810

原创 代码随想录刷题笔记 Day 58 | 判断子序列 No.392 | 不同的子序列 No.115

本题是要查询 s 中有多少种方法可以得到 t,比如第一个案例 s = “rabbbit”, t = “rabbit”,首先来考虑如何划分这个子问题:既然我去查询 s 有多少种方法可以得到 “rabbit” 比较困难,那能否先去找方法得到 “t” 呢?在这种情况下,你会怎样改变代码?s 的前 m 个元素和 t 的前 n 个元素的公共子序列的长度,是可以通过 m - 1 和 n - 1 组成的公共子序列的长度推出的。表示 s 的钱 i - 1 个元素和 t 的前 j - 1 个元素构成的最长公共子序列的大小。

2024-03-26 17:19:56 1049

原创 代码随想录题解 Day 57 | 最长重复子数组 No.718 | 最长公共子序列 No.1143 | 不相交的线 No.1035 | 最大子数组和 No.53

又是一个关于子数组的题目,子数组也就代表着连续,这样就代表着状态中必须包含以什么为 结尾。所以本题中的状态就可以初步确定为以 nums[i] 为结尾的数组的最大的总和。

2024-03-25 17:14:56 585

原创 代码随想录刷题笔记 Day 56 | 最长递增子序列 No.300 |最长连续递增序列 No.674 | 最长重复子数组 No.718

本题的初始化和之前有所不同,注意这个递推公式:dp[i][1] = Math.max(dp[i][1], dp[j][1] + 1); 如果简单的将这个值初始化为 0,那如果前面没有比 num[i] 小的值,那这个值就会 保持 0,而通过题意可以直到,这个值应该为 1。所以所有的 dp[i][1] 都应该初始化为 1。

2024-03-21 23:35:06 591

原创 代码随想录刷题笔记 Day 55 | 买卖股票的最佳时机含冷冻期 No.309 | 买卖股票的最佳时机含手续费 No.714

本题仍然是讨论第一天的初始化。对于买入的状态很容易,为 -prices[0];而对于卖出的状态,可以知道,第一天对于卖出的状态是没有意义的,所以要考虑初始化成什么不会对第二天产生影响,先来看这个状态在第二天哪里用到了:

2024-03-20 15:05:56 953

原创 代码随想录刷题笔记 Day 54 | 买卖股票的最佳时机 III NO.123 | 买卖股票的最佳时机 IV No.188

因为第一次使用的是下标为 0 的部分,所以 temp2 的值是不需要初始化的,这样就完成了递推公式的推导。再来看初始化,直接初始化为 Integer.MIN_VALUE 是有可能引发越界的,上一题因为只初始化了第一天所以不会产生影响,而本题就不同了。所以要找一个比所有卖出状态下 dp 数组的值还要小的一个值来初始化数组。而恰好题目中提到了,prices[i]

2024-03-18 10:14:29 838

原创 代码随想录刷题笔记 Day 53 买卖股票的最佳时机 No.121 | 买卖股票的最佳时机 No.122

与贪心沿着固定的路径进行不同,动态规划其实更偏向于穷举,所以本题的动规解法的时间肯定是要长于贪心的。首先来明确本题中的 状态 是什么,是在某一天通过买卖股票所持有的金钱,但为了描述这个状态,会出现两种情况:当前处于买入的状态,也就是手中还持有股票,持有的金钱为 负数,因为此时只有支出当前处于卖出的状态,手中的股票已经被卖出,持有的金钱为 正数需要注意的是,某一天处于的是 买入 或者 卖出 的 状态,而不是说股票是在这一天买入或者卖出的。

2024-03-17 14:48:18 870

原创 代码随想录刷题笔记 Day 52 | 打家劫舍 No.198 | 打家劫舍 II No.213 | 打家劫舍III No.337

除此之外就没有任何差异了。所以大致可以把本题分为三种情况:第一个和最后一个都不要要第一个但是不要最后一个要最后一个不要第一个注意这里说的要或者不要不是说一定会去偷第一家或者最后一家,而是要不要考虑偷这两家的情况,所以第一种情况其实是包含在第二种和第三种情况之中的,所以只需要求最后两种情况,然后返回其中的。

2024-03-15 17:31:17 733

原创 什么是 HTTPS?它是如何解决安全性问题的?

HTTPS(HyperText Transfer Protocol Secure)是一种安全的通信协议,用于在计算机网络上安全地传输超文本(如网页、图像、视频等)和其他数据。它是 HTTP 协议的安全版本,通过使用加密技术来保护通信的安全性和隐私性。HTTP 是超文本传输协议,信息是明文传输,存在安全风险的问题。HTTPS 则解决 HTTP不安全的缺陷,在 TCP 和 HTTP 网络层之间加入了SSL/TLS安全协议,使得报文能够加密传输。HTTPS 在 TCP 三次握手之后,还需进行SSL/TLS。

2024-03-15 11:31:30 1460 2

原创 代码随想录刷题笔记 Day 51 | 单词拆分 No.139 | 多重背包理论基础

其实从第三行开始就没有什么区别了,这是为什么呢?物品价值为 2,第三行就是尝试将 3 个物品放入背包中,但是背包的总容量为 5,所以后面的遍历其实是没有意义的。这样其实就知道,对于一个物品只需要遍历 `k * weight[i]

2024-03-14 23:37:28 793

原创 面试题:从输入网址到页面显示的全过程(超详细解析)

为了解决进程到进程的问题,发送的信息要借助 TCP 的力量了,TCP 的报文中封装了源端口号和目的端口号,通过这两个字段就可以保证找到需要传递信息的应用。因为需要 TCP 发送的内容可能很长,TCP 会将其分成一段一段的去发送,就需要一个序号来标识此时发送的是哪份内容;同样的,当对方收到报文后也要告诉发送方 我收到了哪个字段,这就是确认号。TCP 没有请求和响应报文,所以需要一个标识位来标识这次的报文是什么内容,例如SYN是发起一个连接,ACK是回复,RST是重新连接,FIN是结束连接等。然后就是。

2024-03-13 15:42:34 1616 2

原创 代码随想录刷题笔记 DAY 50 | 爬楼梯 进阶版 | 零钱兑换 No. 322 | 完全平方数 No.279

而同时如果一个节点是初始化的值,也恰好说明是无法通过这个节点的状态去推出其他节点的,所以到遇到值仍然是初始化的值的节点应该。当 m = 2,n = 3 时,n = 3 这表示一共有三个台阶,m = 2 代表你每次可以爬一个台阶或者两个台阶。遍历顺序:由于本题不涉及排列组合问题,是一个类似于完全背包的题目,所以先遍历背包还是先遍历物品都可以。(由于本题是完全背包问题所以这里的取是指的某一个硬币),如果要取得话,是要建立在。本题也是一个类背包问题,给定一个背包容量,问装满这个背包。

2024-03-12 13:47:27 1005

原创 代码随想录刷题笔记 DAY 43 | 完全背包基础 | 零钱兑换 II No.518 | 组合总和 IV No.377

因为这里这里是按照物品,从上往下取遍历的,推导一个元素依赖的是它的 左上角 的元素,而因为是遍历物品的原因,它的左上角是一定不会含有本元素,因为上层中不会出现 2 所以就不会出现 2 1 和 1 2 这种重复的情况。

2024-03-11 17:14:59 729

原创 代码随想录刷题笔记 DAY 42 | 最后一块石头的重量 II No.1049 | 目标和 No.494 | 一和零 No.474

这里设加法部分的总和为 m 减法部分的总和为 n,则可以得出 m - n = target,而又直到m + n = sum,则可以有 m - (sum - m) = target 最终可以推导出 m = (target + sum) / 2 所以本题又变成了,从数组中选取元素,元素的总和能达到 (target + sum) / 2 的方式有多少种。通过这个方程其实可以推出本题的一些判断条件如果计算出来的 m 是分数的话,那可以直接返回 0,因为题目中给出的全是整数,不可能出现分数的情况

2024-03-10 22:57:02 927

原创 中科大计网学习记录笔记(十八):网络层:数据平面:导论

静态配置和管理: 在传统网络中,网络设备的配置和管理通常是静态的,需要手动配置每个设备的路由信息、访问控制列表(ACL)等,这样的配置不够灵活和自动化,容易导致配置错误和网络故障。硬件依赖性: 传统网络通常依赖专用硬件设备,如路由器、交换机等,这些设备成本高昂且功能相对固定,难以快速适应不断变化的网络需求。难以扩展: 传统网络的扩展性有限,当网络规模增大或者需要新增功能时,往往需要进行大规模的更改和升级,这会增加管理和维护的成本。难以实现灵活的流量控制。

2024-03-10 19:02:18 683

原创 代码随想录刷题笔记 DAY 42 | 背包问题 - 二维 | 背包问题 - 一维 | 分割等和子集 No.416

这道题是背包问题的一个经典的实例问题,其实一开始看到这个题的时候并没有想到往背包方向靠的思路,而是当成了组合问题去做,但是在写的时候突然想到,这不就是 找一个子集,使得它们的和等于原集合和的一半 嘛?再继续深入的想一下,如何才能凑出这个原集合的和的一半值呢?为了好表述这里将这个值设为 target,只考虑子集的和 小于或者等于 target 的情况,这个问题就可以转化为:从集合中的所有元素中选取元素,刨去大于 target 的那部分,它们的和的最大值能否达到 target?

2024-03-06 13:27:01 750

原创 中科大计网学习记录笔记(十七):拥塞控制原理 | TCP 拥塞控制

💡 当网络中的流量超过了网络资源的处理能力时,就会发生拥塞,导致数据包丢失、延迟增加和带宽利用率下降。拥塞是指网络中出现了过多的数据流量,导致网络设备(如路由器、交换机)无法及时处理所有传入的数据包,进而导致缓冲队列溢出,丢包等问题。CongWin:Congestion Window,拥塞窗口Threshold:阈值🍀 当,发送端处于慢启动阶段,窗口指数增长🍀 当,发送端处于拥塞避免阶段,窗口线性增长🍀 当收到三个重复 ACK的时候,Threshold设置成🍀 当超时时间发生的时候,

2024-03-03 21:53:15 993

原创 代码随想录刷题笔记 DAY 41 | 整数拆分 No.343 | 不同的二叉搜索树 No.96

这其实就是第二种情况的最优解,因为此时可以保证拆分出来之后乘积达到最大。数组中取出的,所以如果没有思路或者考虑递归的时候可以先从。完全相同的结构,将这个结构作为左子树;解释: 2 = 1 + 1, 1 × 1 = 1。的时候构成二叉树的结构,那是不是可以这样表示呢?的最大值,那如果是以上的情况其实就默认拆分成。返回满足题意的二叉搜索树的种数。个节点组成的不同的二叉搜索树有多少种。💡 这里说的相同的结构上的相同,指的是。

2024-03-03 18:33:01 773

原创 代码随想录刷题笔记 DAY 38 | 不同路径 No.62 | 不同路径II No.63

题目中问的是共有多少条路径,那是不是可以尝试将到达某个节点的方法种数作为状态呢?再来思考这个状态能否可以转移呢?因为机器人 只能 往下和往右移动,所以到达一个节点的方式是可以依据这个节点的上面和左边推导而来的;这样 状态转移方程 也较为容易的能列出。既然某个节点的状态需要右边和上面列出,那必须要保证一开始最上面那一行和最左边那一列是初始化的,既然机器人只能 向下 和 向右 移动,那这两列都可以初始化为 1 ,因为到达这两个位置的任意一个节点都只有 一种方法。

2024-03-03 00:45:45 915

原创 代码随想录刷题笔记 DAY 37 | 动态规划理论基础 | 斐波那契数 No.509 | 爬楼梯 No.70 | 使用最小花费爬楼梯 No.746

其实贪心算法和动态规划算法的区别还是比较大的,贪心算法每一次的最优解一定包含上一次的最优解,是局部的最优推出全局的最优,而动态规划的最优解不一定包含前一次的最优解,而是有可能是由更前面的部分推出的,所以通常通过 `dp[]` 数组来将前面的所有最优解来保存下来。

2024-03-02 00:46:24 886

原创 Java 学习企划——Stream 流部分

💡 Stream 是 Java 8 中引入的一个新的抽象概念,它提供了一种更为便捷、高效的方式来处理集合数据。Stream 可以让开发者以声明式的方式对集合进行操作,而不需要显式地使用循环或者条件语句。

2024-03-01 12:31:53 1346

原创 中科大计网学习记录笔记(十六):面向连接的传输:TCP

TCP 实现了点对点的通信TCP 提供了 可靠的、按顺序的字节流服务字节流代表需要上层自己维护边界TCP 是流水线协议,即一次可以发送多个报文段TCP 提供了流量控制,发送方根据接收方的接收能力进行发送速率的调整💡 TCP 提供了可靠的数据传输服务。🍀 TCP 在 IP 提供的不可靠服务的基础上建立了 RDT(可靠数据传输)。TCP 具有管道化的报文段其具有累计确认的特点(像 GBN)发送端有单个重传定时器(像 GBN)接收端是否接收乱序没有规范,又接收端自己决定。

2024-02-28 14:13:57 1400 4

原创 代码随想录刷题笔记 DAY 35 | 无重叠区间 No.435 | 划分字母区间 No.763 | 合并区间 No.56

现在来思考如何判断两个段是否重合呢?答案是当发现上一段的 `right` 是大于下一段的 `left` 的时候说明两端是重合的,因为经过排序以后上一段的 起点一定小于等于下一段的起点。这时候为了使得没有重叠是 **一定要删除其中的一段的**,那删除那一段好呢?答案是删除 `right` 最大的段,因为这种段的 **覆盖面积** 最大;所以可以得到这样的策略:遍历数组时当发现有重叠后就删除两段之中 `right` 最大的段。所以在上一张图中,删除的就是第二个段,找不出反例,试试贪心。

2024-02-27 20:45:34 831

原创 代码随想录刷题笔记 DAY 34 | 柠檬水找零 No.860 | 根据身高重建队伍 No.406 | 用最少的箭引爆气球 No.452

本题的情况较少,只有三种情况,这也就导致了本题的解法很简单。在 5 10 和 20 中,如果要找零的话,5 是比 10 的作用更大的,所以我们要尽可能多的去保留 5,来应对后面找零的情况。

2024-02-26 14:37:10 615

原创 中科大计网学习记录笔记(十五):可靠数据传输的原理

前前言:看过本节的朋友应该都知道本节长度长的吓人,但其实内容含量和之前的差不多,老师在本节课举的例子和解释比较多,所以大家坚持看完是一定可以理解透彻的。本节课大部分是在提出问题和解决问题,先明确出现的问题是什么再去看 RDT 是如何解决它的会很有帮助;在 RDT 之后又引入了流水线协议去解决 RDT 利用效率问题,这部分同样需要先搞清楚提出了什么问题。

2024-02-25 21:05:28 940

空空如也

空空如也

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

TA关注的人

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