- 博客(67)
- 收藏
- 关注
原创 C++算法(15)BFS_FloodFill
的遍历,修改性质要改得越早越好,不然遍历同层的节点时会把已经加入队列的节点重复加入,多了一些冗余的步骤,仔细想想,仍然觉得是根节点修改性质,找到新节点后也即刻修改比较好,效率应该是最高的。上一道题是从题给初始位置开始查找,相当于只找一个岛屿,现在是找二维数组中的所有岛屿,故要对每一个方格进行遍历,然后进行BFS的逻辑,具体的不再赘述,但仍然按照上一道题的写法是会超出时间限制的,问题在于:修改性质的方法,在上一题中以为是在分析队列的每一个节点时修改会好一点,因为这样逻辑比较清晰,然而这道题涉及。
2026-03-30 22:10:37
360
原创 C++算法(14)优先级队列
1046. 最后一块石头的重量 - 力扣(LeetCode)明确了优先级队列的作用后,这道题就已经不难写了,先把所有元素入堆,再每次取堆顶的两个元素,看这两个元素的情况根据题目的要求全部出堆或处理后入堆一个。heap.pop();if(cur1!
2026-03-26 21:05:18
361
原创 C++算法(13)队列+宽搜
首先将N叉树的根节点放入队列中,当队列中存在元素则进入循环,保存此时队列元素的个数,因为要将队列个数的节点出队头,每出一个队头则将此队头的子节点入队,每次循环即是提取该层元素并将下层元素全部入队的过程。储存节点时多存一个二叉树下标,以键值对的方式储存,可以不存在队列里,直接以数组的方式储存,对于每一层节点,取出第一个节点和最后一个节点的下标值求出长度,即可获得层宽。注意细节:若子节点为空,则不入队,那么最后一层出队完毕后也不会有节点入队,退出最外层循环。
2026-03-23 00:15:47
214
原创 C++算法(12)栈
这道题的思路也不难想:遍历pushed数组,先将数组元素放入push数组中,再观察栈顶是否和poped指针所指元素一致,若是,则去除push的栈顶,poped指针向后移动(这是一个循环过程),对于pushed每一个遍历到的元素,入栈后都会处理到将可以出栈的全部处理完毕,所以退出循环后,若poped的指针没有走到尽头,则false,否则true。例如2[2[y]]的意思是将2[y]拼接到空字符串上,2[a2[y]]则很明显是将2y拼接到"a"上。这道题的思路有些复杂,需要弄清楚每一种情况的操作和处理。
2026-03-21 13:40:05
394
原创 C++算法(11)字符串
由于储存单位相乘的结果不能用字符串,故用数组tmp,分析可得,数组的长度应为n1+n2-1num1和num2都要逆序,若num1和num2都逆序了,那么单位相乘的结果刚好可以放在tmp[i+j]的位置,且是+=,最后将处理后的字符逆序即可。
2026-03-14 13:41:36
315
原创 C++算法(10)哈希表
哈希表是存储数据的容器,可以快速查找某个元素,需要频繁查找某个元素的时候就可以用哈希表,或者用二分算法(还是尽量用二分,因为哈希表的空间复杂度较高),可以用容器创建哈希表或用数组模拟简易哈希表,建议尽量用数组,因为比较快,容器的创建也要花一点时间,另外还建议在数据范围很小的时候用数组。
2026-03-11 22:42:14
383
原创 C++算法(9)链表
由于每进行一组时需要上一组的头节点作为头插前节点,所以在进行一组前先保存好cur,出大循环后,cur有可能指向NULL(刚好是整数组K),也有可能指向非NULL(还有一些多余的节点),此时prev已准备好,prev->next=cur,返回ret=newhead->next。另外为了方便插入数据,需要创建一个头节点,还需创建一个指针一直指向新创建的需要返回的链表的尾节点,便于插入新的节点,两数相加的进位最多是1,所以每次循环把t的个位作为新节点的值,t/=10得到进位。
2026-03-09 17:50:15
371
原创 C++算法(8)分治-归并
这道题的主逻辑几乎和查找逆序对一样,唯一不同的是在逆序对那里,tmp复制元素排序和统计逆序对的个数是在同一个循环里进行的,而这道题不行,因为tmp复制元素排序的条件是nums[cur1]>nums[cur2](升序),而这里统计翻转对的条件是nums[cur1]>2*nums[cur2](升序),所以不能同时进行,需要分开写,先统计完翻转对个数,再复原cur1,cur2进行排序,总体来说并不难写,还有一个需要注意的问题:2*int可能会溢出,所以要么计算的时候强转成。每次进入函数定义一个ret记录。
2026-03-04 23:15:41
376
原创 C++算法(7)分治-快排
当nums[i]==2时,swap(nums[--right],nums[i]),交换之后,nums[i]为一个未扫描的数,nums[right]为2,此时i不用++,因为要扫描当前的,所以写成swap(nums[--left],nums[i])当nums[i]==0时,nums[++left]与nums[i]交换,交换之后nums[i]为1,nums[left]为0,符合要求,i继续向前扫描,i++,那么可以写成swap(nums[++left],nums[i++])当nums[i]==1时,i++
2026-02-27 19:15:23
494
原创 C++算法(6)模拟
另外有一个细节要处理:当numRows=1时,d=0,会进入死循环,所以要在代码开头先判断一下numRows是否为1,如果是,则代表直接返回字符串即可。观察可知,第0行每个下标之间相差6(d),也就是圈起来的元素个数,可知第二列是一定会有两个空格的,所以d=2*numRows-2。第numRows-1行,观察可得:n-1->n-1+d->n-1+2d->...->n-1+kd。第K行:观察可得:(k,d-k)->(k+d,d-k+d)->...所以,第0行:0->0+d->0+2d->...->0+kd。
2026-02-24 15:57:39
585
原创 C++算法(5)位运算
进入循环先判断该字符在位图中的位置是0还是1,是1则表示已经存在过了,直接false,是0则存入。③位运算 创建一个不缺失的数组(不用真的创建,遍历的i就可以当作数组元素),和nums中的所有元素全部异或起来,得到的值就是缺失的数字。(若原位为0,则得到的数为0,若原位为1,则得到的数为1)可见,处理后的数位和要找的数的数位是一一对应的,所以可以循环遍历32个数位,将处理后的数填充到其中即可。只有1+1会产生进位,所以凡有0的进位都是0,用&
2026-02-21 23:58:15
579
原创 C++算法(4)前缀和
要在以i位置为结尾的所有子数组中找和为K的,即在[0,i-1]区间内,有多少个前缀和等于sum[i]-k(用哈希表储存<int,int>),如果sum[i]-k==0,就会去找前缀和为0的数组,但[0,-1]区间不存在,所以要提前把hash[0]=1;dp[i]表示[1,i]区间内所有元素的和,dp无需遍历求和,dp[i]=dp[i-1]+arr[i],dp[0]=0;sum[i]的最大范围是[0,i-1],当它为[0,-1]时情况也应是存在的,所以手动给hash[0]=-1;
2026-02-19 15:30:26
591
原创 C++算法(3)二分算法
34. 在排序数组中查找元素的第一个和最后一个位置 - 力扣(LeetCode)暴力解法的时间复杂度为,在数组中全是目标元素的情况下,朴素二分查找的时间复杂度也是,要找更优的算法当x<target时,将left移至mid+1当x>=target时,将right移至mid循环条件:left<right1>数组中有结果时:right最终停留在mid处,left跳出[left,mid-1]的区域和right站在同一位置,此时所指位置即为ret,无需再判断进入循环,否则死循环。
2026-02-15 17:17:14
582
原创 C++算法(2)滑动窗口
首先定义left和right两个指针,right不断将字符放进哈希表里,直到遇到重复字符,此时left指针再直接继续枚举是没有意义的,由于题目要的是最长子串,只要left没有越过重复字符,则得到的子串必然短于当前,所以应该使left越过重复字符(若这个字符一直在哈希表中的值大于1,则说明出窗口的操作一直没有越过重复字符)。count统计的是有效字符的个数,如果入窗口之后,对应哈希表的值大于标准哈希表的值,那么这个字符必定是无效的,故反之有效,count++
2026-02-13 02:04:16
627
原创 C++算法(1)双指针
在开启这个新的专题之前,仍然照常写一些前言类的东西吧,这个专题本应该是我在完成学习C++这个专题之后再开始的,然而比赛将至,我目前觉得C++学习这个专题的内容暂时够用,所以不得不先放下C++基础的学习,转而学习算法,当然我还是觉得C++以及后续Linux系统的学习是我学习的主路线,所以这部分是必然不会放下的。那么到了算法这边,我觉得是一种新且不同的学习方法和内容,这可能对学习者个人的逻辑思维方面要求较高,总而言之是一种新的挑战,那么当然也希望在此过程中可以得到收获和提升。
2026-02-08 17:47:12
667
原创 学习C++(7)初始化列表+隐式类型转换+static成员
既然在初始化列表显式初始化了成员变量,那成员变量声明处加的缺省值就可以直接忽略。初始化列表中按照成员变量在类中声明顺序进行初始化,所以先初始化的是_a2,此时_a1还没有被初始化,故是随机值,_a2被赋为随机值,再初始化_a1,_a1用传递的参数初始化,被初始化为1。①初始化列表中按照成员变量在类中声明顺序进行初始化,跟成员在初始化列表出现的的先后顺序无关,建议声明顺序和初始化列表顺序保持一致。③无论是否在初始化列表显式初始化成员变量,每个成员变量都要走初始化列表初始化,所以尽量使用初始化列表初始化。
2026-02-02 23:56:11
383
原创 学习C++(6)日期类的实现+取地址运算符重载
GetMonthDay不做声明和定义分离,因为这个函数必定会被频繁地调用,直接定义在类里面,则默认为内联函数,调用时直接展开,避免建立函数栈帧,提高效率。前置++、后置++、前置--、后置--的实现并不难,只需要分清前置和后置的概念即可,前置则返回++后的类,后置则返回++前的类,但无论是后置还是前置,类都经过了+=1的过程;以下是一个较简单的实现方法,先判断两个日期类的大小,再让小的日期不断++,直到等于大的日期,在这个过程中计数,++了多少次就相隔了多少天。第二种方法中+拷贝了两次,+=拷贝了三次。
2026-02-01 19:46:49
588
原创 学习C++(5)运算符重载+赋值运算符重载
赋值运算重载的参数建议写成 const 当前类类型引用,可以提高效率,返回值也建议写成当前类类型引用,有返回值是为了支持连续赋值场景。①没有显式实现时,编译器会自动生成一个默认赋值运算符重载,默认赋值运算符重载行为跟默认拷贝构造函数类似,对内置类型成员变量会完成值拷贝,对自定义类型成员变量会调用它的赋值重载函数。当运算符被用于类类型的对象时,C++允许通过运算符重载的形式指定特定的含义。C++规定类类型对象使用运算符时,必须转换成调用对应运算符重载,若没有对应的运算符重载,则会编译报错。
2026-01-30 23:33:13
334
原创 学习C++(4)构造函数+析构函数+拷贝构造函数
像Stack这样的类,虽然成员变量也都是内置类型,但是_a指向了资源,编译器自动生成的拷贝构造完成的浅拷贝会使两个类中的指针指向同一块空间,该空间会被析构两次,程序运行会崩溃,所以需要自己实现深拷贝(对指向的资源也进行拷贝)。⑦编译器默认生成的构造,对内置类型成员变量的初始化没有要求,(可以直接认为编译器不初始化),对于自定义类型成员变量,要求调用这个成员变量的默认构造函数初始化,如果这个成员变量没有默认构造函数,那么就会报错,要初始化这个成员变量,需要用初始化列表才能解决。③一个类只能有一个析构函数。
2026-01-29 23:57:20
607
原创 学习C++(3)类的概念+类实例化出对象+this指针
class为定义类的关键字,Stack为类的名字,{}中为类的主体,类定义结束时后面分号不能省略,类体中内容称为类的成员,类中的变量称为类的属性或成员变量;类中的函数称为类的方法或者成员函数。为了区分成员变量,一般习惯上成员变量会加一个特殊标识,如成员变量前面或者后面加_或者m 开头,这并不是C++规定的,只是一些惯例,具体看公司的要求。
2026-01-28 17:18:36
555
原创 学习C++(2)缺省参数+引用+inline函数+nullptr
缺省参数(也叫默认参数)是声明或定义函数时为函数的参数指定的一个缺省值( 函数声明和定义分离时,缺省参数不能在函数声明和定义中同时出现,规定必须在函数声明给缺省值)。①必须用const引用引用一个const对象,const引用也可以引用普通对象,因为对象的访问权限在引用过程中可以缩小,但是不能放大。引用不是重新定义⼀个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空间, 引用变量和它引用的变量共用同一块内存空间。在链表中,由于引用不能改变指向,引用必须初始化,所以引用不能代替指针。
2025-10-06 00:59:15
453
原创 学习C++(1)命名空间+输入&输出+函数重载
经过一段时间C语言的学习,虽然中间有差不多半年的时间没有继续学(忙于学校的课程),总之C++的部分终于开启了,作者我在学C语言的时候就比较向往C++,因为身边的计算机专业同学是从C++开始学起的,给作者的感觉是更难且更高级一些,在作者看来,学习一门类似C++这样专业性较高的语言像是踏进了一个新的门槛,能看到一个全新的世界,我也非常愿意在这个过程中一步一步地感受到自己的提升,那么,像刚开始学习C语言时我发的第一篇博客一样,做一个自我介绍:我是一名大二的学生,对于计算机语言有很高的学习兴趣,为了熟练掌握计算机语
2025-09-13 00:28:41
612
原创 学习数据结构(16)快速排序
快速排序的基本思想:快速排序是Hoare于1962年提出的一种二叉树结构的交换排序方法,其基本思想为:任取待排序元素序列中的某元素作为基准值,按照该基准值将待排序集合分割成两子序列,左子序列中所有元素均小于基准值,右子序列中所有元素均大于基准值,然后左右子序列重复该过程,直到所有元素都排列在相应位置上为止。
2025-09-02 01:05:11
792
原创 学习数据结构(15)插入排序+选择排序(上)
最后将arr[imin]的值和arr[begin]的值交换,arr[imax]的值和arr[end]的值交换,begin往前移一位,end往后移一位。有一个需要注意的点:当最大值就是arr[begin]时,此时arr[imin]先和arr[begin]交换,那么imax标记的是最小值,arr[imax]再和arr[end]交换就会出错,解决方法是把imin赋给imax,此时arr[imin]先和arr[begin]交换,imax标记的就是最大值,再将arr[imax]和arr[end]交换。
2025-08-31 15:56:19
935
原创 学习数据结构(14)二叉树OJ
若传入的根节点为空,返回true,在不为空的情况下,若左子树节点存在且根节点的值与左子树节点的值不一致,返回false,若右子树节点存在且根节点的值与右子树节点的值不一致,返回false,若以上判断都为真,继续遍历左子树和右子树,只有当左子树和右子树返回值都为true时,函数才返回true。先将输入的字符串储存到数组中,在创建二叉树的函数中,若遍历到'#',返回NULL,否则依据值创建二叉树节点,并对当前创建的节点的左右指针递归调用函数,返回当前节点的指针。对创建好的二叉树通过递归进行中序遍历。
2025-08-30 01:08:51
1183
原创 学习数据结构(13)二叉树链式结构下
循环判断队列是否为空,若不为空则提取队头数据,将队头出队,若队头数据不为空指针,则二叉树为非完全二叉树,销毁队列,返回false,若直到跳出循环队头数据一直为空指针,则二叉树为完全二叉树,销毁队列,返回true。若给出二叉树的前序序列,则序列中第一个即二叉树的根节点,若给出二叉树的中序序列,则根节点左右两侧的序列分别是根节点的左子树和右子树,若给出二叉树的后序序列,则序列中最后一个即二叉树的根节点。④某二叉树的后序遍历序列与中序遍历序列相同,均为ABCDEF,则按层次输出(同一层从左到右)的序列为(A)
2025-08-28 23:12:26
373
原创 学习数据结构(12)Top-K问题+二叉树链式结构上
以求前K个最大的数据为例,假设数据集合中有N个数据,首先用数据集合中前K个数据建小堆(若要求前K个最小的数据则建大堆),然后将剩余N-K个数据依次和堆顶数据做比较,若数据大于堆顶数据则入堆并调整,遍历完数据集合后,堆中的数据就是数据集合中前K个最大的元素。链式结构二叉树的节点由三个域组成,数据域和左右指针域,左右指针分别指向该节点的左孩子和右孩子,若无孩子,则指向NULL。Top-K问题即求大量数据中最大或最小的前K个数据,由于数据量较大,一般的方法都不可取,故使用堆的方式解决问题。
2025-08-27 09:15:48
249
原创 学习数据结构(11)二叉树(堆)下
如果有⼀个集合 K = {k0,k1,k2,...,k(n-1)} ,把它的所有元素按完全二叉树的形式存储在一个一维数组中,并满足:K(i)<=2*i+1且K(i)<=2*i+2(K(i)>=2*i+1且K(i)>=2*i+2),i=0,1,2... ,则称为小堆(或大堆),将根结点最大的堆叫做最大堆或大根堆,根结点最小的堆叫做最小堆或小根堆。通过向上调整或向下调整将数组排列成堆的结构(若要排升序,则建大堆,排降序,则建小堆),将数组开头的元素和末尾的元素交换,将此时数组开头的元素看作双亲,向下调整。
2025-02-19 22:23:09
715
原创 学习数据结构(10)栈和队列下+二叉树(堆)上
将不为空队列中前Size-1个元素入队列进另一个为空的队列中,同时将前Size-1个元素从不为空队列中出队列,则原先不为空队列中只剩一个元素,取队头数据,再将此数据出队列,返回队头数据。先判断q1队列是否为空,若为空,则将元素入队列q1,否则将元素入队列q2,即将元素入队列进不为空的队列中,但第一次入队列时,尽管q1,q2都为空,元素仍会入队列q2。题目要求实现的函数有六个,分别是初始化队列,入队列,从队列开头移除并返回元素,返回队头元素,判空,销毁队列。当s1和s2都为空时,MyQueue为空。
2025-02-15 23:29:36
807
原创 学习数据结构(9)栈和队列上
遍历字符串,遇到左括号则入栈,遇到右括号时,判断栈是否为空,是则,销毁栈,直接返回false,不是则取栈顶数据,判断栈顶数据是否与右括号相对应,是则将栈顶数据出栈,不是则销毁栈,直接返回false,循环结束,判断栈是否为空,为空则说明括号全部配对,返回true,不为空则只有一种可能:栈中有未配对的左括号,返回false。队列是只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出的特点,进行插入操作的一端称为队尾,进行删除操作的一端称为队头。
2025-02-13 00:23:41
412
原创 学习数据结构(8)双向链表
顺序表在随机访问,频繁访问上具有优势,链表在任意位置插入或删除数据上具有优势,顺序表可能存在空间浪费,链表不存在空间浪费。传一级指针:(能保持接口一致性)双向链表一般指带头双向循环链表。
2025-02-10 20:45:08
493
原创 学习数据结构(7)单链表OJ下+链表分类
C为环形部分的周长,假设slow刚到入环节点时,fast在如图所示的位置,此时fast与slow之间的距离为N,由于fast每次走三步,slow每次走一步,所以每运动一次fast和slow之间的距离就会减少两步,若N为偶数,则N不断减2最终可以为0,即fast和slow相遇,若N为奇数,N会减为-1,此时slow和fast错过,fast和slow之间的距离变为C-1,若C-1为偶数(即C为奇数),则fast和slow可以相遇,若C-1为奇数(即C为偶数),则fast和slow还是不能相遇,最终也不会相遇。
2025-02-09 11:12:50
1052
原创 学习数据结构(6)单链表OJ上
创建新的空链表,在两个指针都不为NULL的条件下,两个指针分别同时遍历两个链表,每次遍历比较节点中数据的大小,小的数据节点尾插到新链表中,退出循环后,将不为空的链表指针以后的所有节点尾插到新链表中,但这种方法由于新链表为空链表,在插入第一个节点时与插入后面的节点写法不同,造成代码比较冗杂。:(我的解法)遍历链表,得到节点个数,节点个数除以二,得到从头节点到中间节点的遍历次数,再遍历链表,找到中间节点,但较复杂。(参考代码)和解法一类似,但对起始的三个相邻节点的选择不同,且更加简洁。
2025-02-07 00:28:12
392
原创 学习数据结构(4)顺序表+单链表
链表中每个节点都是独立申请的(即需要插入数据时才去申请⼀块节点的空间),需要通过指针 变量来保存下一个节点位置才能从当前节点找到下一个节点。节点⼀般是从堆上申请的,从堆上申请来的空间,是按照⼀定策略分配出来的,每次申请的空间可能连续,可能不连续。链表是⼀种物理存储结构上非连续的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。节点的组成主要有两个部分:当前节点要保存的数据和保存下⼀个节点的地址(指针变量)链式结构在逻辑上是连续的,在物理结构上不⼀定连续。
2025-01-29 16:08:29
574
原创 学习数据结构(3)顺序表
(注意要保证有效数据个数不为0且pos大于等于0,小于有效数据个数,当pos等于0时相当于头部删除,当pos等于有效数据个数-1时相当于尾部删除)(注意要保证pos大于等于0,小于等于有效数据个数,等于0时相当于头部插入,等于有效数据个数时相当于尾部插入)(这里注意要保证有效数据个数不为0)
2025-01-28 11:57:51
618
原创 学习数据结构(2)空间复杂度+顺序表
函数栈帧在编译时已经确定了,只需要关注函数在运行时额外申请的空间,有size_t end、size_t i、int exchange 三个额外创建的变量,F(N)=3,故空间复杂度为O(1)顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储,顺序表的底层结构是数组,对数组的封装,实现了常用的增删改查等接口。递归算法的空间复杂度=单次递归的空间复杂度*递归次数,每调用一次递归函数开辟一个函数栈帧,这里调用了N次,空间复杂度为O(N)(这是作者在百度上找的图)
2025-01-26 23:45:06
1527
原创 学习数据结构(1)时间复杂度
若要查找的字符在字符串第一个位置,T(N)=1,若要查找的字符在字符串最后一个位置,T(N)=N,若要查找的字符在字符串中间位置,T(N)=N/2或N/2+1(N是偶数),或T(N)=(N+1)/2(N是奇数),因此,Fucn5的时间复杂度分为:最好情况:O(1),最坏情况:O(N),平均情况:O(N)T(N)=M+N,若M和N相差不大,T(N)可看成2N或2M,若M>>N,T(N)=M,若M<<N,T(N)=N,故时间复杂度为O(N)T(N)=N^2+2*N+10,只保留最高次项,则时间复杂度为O(N)
2025-01-25 20:20:25
961
原创 复习C语言(2)
strlen函数遇\0结束,所以要找数组中第一次出现0的位置,由于数组是字符型数组,所以只需使-1--i补码的后八位全为0即可,-1的补码为11111111111111111111111111111111,当i=255(00000000000000001111111111111111)时,a[i]为0,所以strlen(a)=255。(3,4)是逗号表达式,逗号表达式的值为最后一个表达式的值,即4,那么数组中有4个元素,共16个字节。5>若输入字符中含有非数字字时,返回非数字自负前面的数字。
2025-01-19 01:48:16
405
原创 复习C语言(1)
按照课程安排,作者的C语言理论学习基本结束,今天开始开一个新的C语言复习系列,收集整理在C语言复习过程中发现的遗漏点以及C语言的编程题。
2024-10-27 18:35:55
298
1
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅