- 博客(47)
- 收藏
- 关注
原创 线程池项目(逻辑清晰)
存储线程的哈希表(由线程id映射到线程),初始线程数量(用来确保cahced模式下最少的线程),线程数量阈值(用来确定cached模式下最多的线程数量,防止线程过多导致崩溃),原子类型的当前线程数量和空闲线程数量(原子类型确保多线程环境下计数的准确性,比如多个线程同时启动)用函数包装器定义一个接收int类型(线程id),空返回类型的函数线程待执行的函数;为每个thread对象生成唯一的线程 ID的参数(每产生一个线程自动++);每个线程对象的id。
2025-03-12 11:26:07
859
原创 代码随想录 二叉树 test 4
初始序列为(4)(2 7)(1 3 6 9),先遍历到4,根据先序递归的规则(根左右),先处理根节点,交换其左右子树,此时序列为(4)(7 2)(6 9 1 3),然后再遍历当前4的左孩子7,处理7,交换其左右孩子,此时序列为(4)(7 2)(9 6 1 3),遍历当前7的左孩子9,交换9的孩子不变,再依次遍历9的左右,为空返回,遍历当前7的右孩子6,交换6的孩子不变,再一次遍历6的左右,为空返回,然后再遍历当前4的右孩子2,处理2,交换其左右孩子,此时序列为(4)(7 2)(9 6 3 1)......
2025-01-26 01:31:49
790
原创 代码随想录 二叉树 test 3
设置pre指针和cur指针,将pre指向当前指针,由于每次外层循环的队列都装满该层结点,因此每次遍历将cur指向队头结点,将pre指向cur即可实现填充右侧指针,同时将两个指针都右移,由于每层第一个结点没有前置指针,因此需要分当前指针指向的是否为本层第一个结点,如果是则将pre和cur都指向当前队头结点。题目要求即为输出每一层的最右结点,因此在入队列时,判断是否为上层队列的最后一个即可,也就是当size减到0时,即为最后一个。由于上题是按层处理的,因此只需将最后的res反转即可实现层的反转。
2025-01-25 16:24:57
314
原创 代码随想录 栈与队列 test 7
首先想到哈希,用key来存元素,value来存出现次数,最后进行排序,时间复杂度约为o(nlogn)。由于只需求前k个,因此可以进行优化,利用堆来维护这k个元素,由于最终要剩下k个最大的元素,因此元素每次加入堆时,要将堆中最小元素弹出,因此要用小根堆来维护。
2025-01-23 22:06:24
180
原创 代码随想录 栈与队列 test 6
pop(),检查当前滑动窗口最后一个元素是否为单调队列的队头,若不是则不用管,这说明该元素不是当前单调队列的最大值,在这之前就已经被丢出单调队列中。每次只取窗口中最大值,这个最大值可能在后面的滑动中保持不变,而比最大值小的值且在最大值之前出现的值没必要保留,因此可以通过单调队列利用这个特性。push(),将当前滑动窗口的第一个元素加入单调队列中,把队列中小于该元素的值全部丢出队列。getmax(),单调队列的队头即为最大值。2.队列具有单调性,队尾为最小值。1.队头始终为当前队列的最大值。
2025-01-23 21:03:12
183
原创 代码随想录 栈与队列 test 4
当字符串为空或者字符串最后一个字符不是遍历的字符,就将正在遍历的字符加入字符串尾部;类似于括号匹配,这里可以采用字符串来模拟栈。
2025-01-20 23:59:20
342
原创 代码随想录 栈与队列 test 3
遇到左括号,将对应的右括号入栈,遇到右括号则出栈顶元素。因此如果对于情况一,则所有括号遍历完之后有剩余,对于情况2,则此时栈为空,对于情况三,此时出栈元素与遍历的右括号不一致。
2025-01-20 23:53:24
221
原创 代码随想录 栈与队列 test 2
用主队和辅助队实现,入栈时主队入队即可,出栈需要将记录此时主队中的元素个数n,将前n-1个元素放入辅助中,此时剩在主队中的一个元素即为栈顶元素,出队。之后再将辅助队赋值给主队,清空辅助队。出队时,重新入队即可。
2025-01-19 20:47:32
271
原创 代码随想录 栈与队列 test 1
用入队栈和出队栈来模拟队列,入队时正常入栈即可,出队时,将栈内元素以栈的方式放入到另一个栈中,再将出队栈出栈即可。显示队头元素可以借助出栈入栈实现。
2025-01-19 20:14:19
238
原创 代码随想录 字符串 test 7
重复子串,那么主串一定由重复子串组成吗。接下来进行剪枝,如果子串是重复子串,那么主串长度一定是子串长度的整数倍。从小到大枚举子串(为主串的前缀)的长度(每次枚举的子串若含重复子串一定匹配失败,因为如果成功会在最初返回),由于子串如果超过主串的一半,一定不会匹配成功,因此可以将枚举长度范围设为[1,n/2]。将两个主串拼接在一起形成一个总串,如果在这个总串中可以找到主串,就说明主串中有重复的子串,注意为了避免将前一半或后一半主串直接当作寻找到的主串,可以将总串的首尾字符删去,因为目的是在内部找到主串。
2025-01-18 16:45:53
282
原创 代码随想录 字符串 test 6(KMP,超详细)
采用next数组从0开始,next数组值即当前位置子串的最长相等前后缀,如ababa,此时最后一个字符a处的最长相等前后缀为"aba",因此他的next数组值为3,同理倒数第二个字符b的next数组值为2,整体next数组为00123,因此如果当前位置j匹配失败(第1个位置特殊讨论),说明他前面的字符s[j-1]匹配成功,此时next[j-1]也就是匹配成功部分的最长相等前后缀大小,说明下次匹配可以直接从该前缀的下一个字符开始匹配,也就是从next[j-1]开始(大小等于序号加1)。
2025-01-18 00:21:34
989
原创 代码随想录 字符串 test 4
整体思路:遍历数组,如果遍历到的不是空格就进入操作,将当前遍历到的单词覆盖掉原数组,为了实现每个单词之间有一个空格,还需要在每次操作时判断当前指针是否在起点,若不在起点,添加一个空格,由于下一次遍历原空格后不符合条件,不进行操作。每个单词反转:采用双指针,设置每个单词的起始指针start,再设置i指针作为每个单词的结尾,即遍历到空格时[start,i-1]之间为一个单词,将该单词反转,之后将start移动到下一个单词的起始即可。分三步,第一步移除多余空格,第二步整体反转,第三步每个单词反转。
2025-01-17 16:25:28
239
原创 代码随想录 字符串 test 3
为了不使用额外的空间,采用双指针,通过用旧指针遍历原数组计算出数字个数,进而计算出新数组应有的大小,然后新指针指向新数组的最后,此时新,旧指针都位于两数组的末尾,同时从后往前遍历,遇到数组,新指针就需要写入number,遇到字母,就赋值旧数组的值。在整个过程中,旧指针先移动到旧指针末尾,然后两个指针一起移动到数组起点,时间复杂度为o(2n+kn)。如果采用从前往后遍历,为了不采用额外空间(若采用时间复杂度与从后往前无异),每次遍历到数字都要将它后面的字符移动到5个位置后,时间复杂度为o(n^2)
2025-01-17 15:24:59
226
原创 代码随想录 哈希 test 8
与三数之和类似,重点在剪枝和去重的区别,由于target可正可负,因此需要分两种情况讨论,如果target为正,则若当前选择的元素之和大于target,需要跳出这种选择,如果target为负,则若当前选择的元素之和大于target,需要跳出这种选择,可以将这两种情况简化(不完全相同)为判断当前选择的元素之和大于target且选择的元素之和>=0(目标值为-100,若元素为-99,-1,0也可以成立),去重与之前类似,注意选择第二个元素时同样需要类似的剪枝。
2025-01-11 00:06:38
295
原创 代码随想录 哈希 test 7
若为0,则将该三元组加入答案中,同时将两个指针分别移动到与本次元素不同的位置(为什么不在本次迭代开始就移动,因为三元组可以是0,0,0),因为如果不移动,之后遇到相同的一定不会出现在答案中(分两种情况讨论,一是当前遍历元素和他后面的元素相同,则会出现重复方案,二是不同,则不会满足方案),之后再将两指针收缩。先进行排序,再进行遍历,设置两个指针l,r指向遍历元素后半段数组的首尾,检查当前遍历元素加上两个指针指向的元素是否为0,若大于0,说明r偏大,需要左移,如果小于0,说明l偏小,需要右移;
2025-01-10 23:25:21
385
原创 代码随想录 哈希 test 6
由于需要判断ransomNote中的字符串是否在magazine中出现且magazine中每个字符只能用一次,因此可以用哈希存magazine中出现的字符作为key,每个字符出现的次数作为value。遍历ransomNote,将每个字符对应的次数都减去一次,如果当前字符已经不足以用哈希表存在的字符补充,则说明magazine不满足。
2025-01-10 01:00:16
152
原创 代码随想录 哈希 test 5
若进一步优化,考虑先遍历一个数组用哈希表记录下已经选择的元素和key,及其出现的个数value,再一起遍历另外三个数组,现在若想找全所有方案,需要根据(因为遍历是不重不漏的)得到每次遍历的三者之和,寻找哈希表中能够与之加和为0的方案数keyx,该方案数就是这次遍历得到的所有组合个数,将res+=keyx,最终就得到全部取法个数,时间复杂度为o(n+n^3);
2025-01-10 00:24:59
312
原创 代码随想录 哈希 test 4
每次遍历时,检查前面有没有哪个值与本次遍历的值相加等于目标和,若有应该返回两个值的下标,因此采用哈希表(通过值映射到下标),每次迭代需要将本次遍历的值加入表中。
2025-01-09 21:52:08
132
原创 代码随想录 哈希 test 3(快乐数)
先写出求每个位的平方和的函数getsum,如果出现死循环,说明至少有一个数被重新计算过(证明:假设没有一个数字被重新计算过,则出现死循环存在两种可能,一是无限循环,二是无限不循环,只需否定这两种情况即可,先否定一,当出现无限循环,则说明有数字重复出现,与条件矛盾,排除一,再否定二,由于对于一个正整数n而言,计算出的getsum(n)一定是有限值x,且为正整数,因此经过无穷次y迭代,一定会使得y>x,说明在y次迭代中在(0,x)内存在重复的数字,因此不存在无限不循环,否定二,得证),所以。
2025-01-09 15:28:51
215
原创 代码随想录 哈希 test 1
用数组实现从下标映射到字母,先遍历一个字符串,每遍历到某个字母在相应下标++,再遍历另一个字符串,每遍历到某个字母在相应下标--。若两字符串拥有的字母相同,最终数组应全为0。
2025-01-09 13:25:04
172
原创 代码随想录 链表 test 7
并且相遇时慢指针一定第一次进入环内(因为相遇位置在环内,不妨将相遇的整个过程简化为从慢指针进入环的起点开始,记录此时快指针的位置为x,由于快指针速度是慢指针的两倍,因此当慢指针走完一圈,快指针一定从x开始走了两圈再次到达x,将环想成一个线性,当慢指针再次到达起点时,快指针一定已经走过该点(无论快指针刚开始在什么位置),想象成跑步,有个人在你后面起跑,结果比你选到达终点,他一定在某一时刻超过你,因此必定在慢指针第一圈内相遇)
2025-01-09 01:01:17
278
原创 代码随想录 链表 test 6
如果两个链表相交,则它们从交点开始到结束共用结点,因此如果两个链表长度不一样,且存在差值len,那么这个差值一定是在交点前产生的,因此如果让指向表长的指针先移动len,再同步移动,如果有交点就会同时到达。
2025-01-08 22:59:00
233
原创 代码随想录 链表 test 5
这样当快指针指向最后一个结点的空指针域时,慢指针指向的结点的next域就是待删除结点。因此关键就是让快指针比慢指针先移动n+1步(两个指针之间存在n个结点,说明其之间有n+1个next指针),然后同步移动直到快指针为空。利用双指针,为了找到倒数第n个结点,可以将快慢指针之间的保持存在。
2025-01-08 22:04:57
177
原创 代码随想录 链表 test 4
设置一个虚拟头节点,将由于需要分奇偶讨论,奇数情况下,如果当前指针后面只剩余一个结点则退出循环,偶数情况下,如果当前指针后面没有结点则退出循环。因此循环条件是cur->next和cur->ne->next都不为空,考虑空表的情况,所以cur初始指向虚拟头节点。每次迭代需要修改的指针如下:(图源代码随想录官网)注意每次修改一个结点的next指针域后,他后面的结点都可能不是原来的结点了。
2025-01-08 20:31:54
234
原创 代码随想录 链表 test 3
在物理和逻辑上都实现对链表原地逆置,利用pre和cur两个指针遍历链表,用tmp指针指向下一个待遍历的结点,防止指针丢失,然后将cur指向的结点的next域反向。(写完才发现代码和头插法是一样的!利用头插法的特性(每次插入的结点位于表头,所以插入的次序和表中次序相反),空间复杂度o(1)子问题:将每次修改后的链表看作原链表的一个子链表,观察这个子表中cur和pre发生了什么变化。递归内容:每次递归时需要将cur指向的结点的next域修改为pre。递归入口:即cur指针和pre指针初始是什么。
2025-01-08 18:27:11
289
原创 代码随想录 链表 test 1
采用虚拟头节点,使操作统一,因为删除时要找到删除节点的前一个结点,如果不采用虚拟头节点就会出现两种情况,即首元节点(不带头节点)和其他结点,因为首元结点前面没有结点所以要特殊处理。
2025-01-08 17:16:07
213
原创 代码随想录 数组test6(区间和与一维前缀和)
由于该类问题要求多个区间的和,因此通过简单的暴力解法会有多次重复的操作,故采用前缀和,使得只遍历一次数组,完成多次请求。
2025-01-07 17:08:07
177
原创 代码随想录 数组test5(leetcode 59.螺旋矩阵)
大致的想法是从起点开始以顺时针走到中心,有两种实现方式:一圈一圈赋值或者每走一步就赋值。
2025-01-07 17:07:51
272
原创 代码随想录 数组test4(滑动窗口)
是一种用于解决数组或字符串相关问题的常用技巧。它通过维护一个窗口(通常是数组或字符串的一个子区间),在遍历过程中动态调整窗口的起始和结束位置,从而高效地解决问题。首先要理解滑动窗口的时间复杂度为什么是o(n),在维护窗口的过程中,每一个元素先被右窗口指针遍历,之后可能会被左窗口指针遍历,即每个元素至多会被遍历两次,即o(2n)的复杂度。主要分为两种类型,即是否固定窗口大小,但二者的。
2025-01-06 18:33:27
280
原创 代码随想录 数组test3
由于最大值一定出现在原数组的两端元素的某一个,因此可以采用双指针,分别指向原数组的首尾,每次选择大的赋值给新数组,由于要求升序,因此需要从后往前对新数组赋值。
2025-01-06 18:33:09
143
原创 代码随想录 数组test2
使用双指针,利用快指针遍历旧数组,慢指针生成新数组。即当快指针遍历到的元素不是要删除的元素,就将其赋值给慢指针的位置。
2025-01-06 15:22:46
134
原创 代码随想录 数组 test 1 (二分详解,包括二分答案)
采用模板1,二分查找目标元素位置,若查到,则返回mid,若不存在,则根据迭代时更新l=mid+1,r=mid-1,可知当循环结束时,如果是l=mid+1导致的,则说明当前l左侧的都比目标元素小,即l当前指向的元素可能大于目标元素,如果是r=mid-1导致的,则说明r右侧的都比目标元素大,即r当前指向的元素可能小于目标元素,由题意,要返回插入位置,因此返回l。采用二分答案的思路,二分插入位置。因此当mid处的方案满足要求时,要将区间压缩为右侧,即更新l指针,l=mid,因此为避免死循环,使用上取整。
2025-01-06 12:51:14
1304
空空如也
请问大家,画红框这里是什么意思,有什么作用(语言-c语言)
2023-02-11
TA创建的收藏夹 TA关注的收藏夹
TA关注的人