- 博客(95)
- 收藏
- 关注
原创 【刷题14】哈希表专题
j = 0 会不会与找到的元素位置下标刚好为0(第一个元素)冲突?因为能到这步的前提肯定是中间的某个元素与第一个元素相加等于target;既然如此,那么遍历到这个中间某个元素是不是之间就已经遍历过第一个元素了,既然刚开始就是第一个元素,那么为什么不这时候找k值呢?k值不就是这个中间的某个元素吗,然后j肯定不是0,并且i不等于j,直接返回就结束了。哈希表统计每个元素出现的个数,大于等于2就返回true,如果没有返回false。哈希表<字符串,字符串数组>思路:哈希表<元素,下标>哈希表<元素,下标>
2024-11-03 19:31:26 231
原创 【刷题12】分治—归并排序
假如内循环是正常走完的,不是break跳出来的,那么根据前面说的,begin1>end1结束,所以内循环结束的下面理所应当要有一个break。但是假如是因为内循环的break到这里来的(ret+=后,begin1还是小于end1的),即内循环还没结束,外循环也没有,就直接跳出了,会出现各种问题。以上图为例:原数组的元素5是下标0,那么它的右侧小于它的元素个数,应该加在hash下标为0的位置上。思路:在逆序对的基础上改变应该条件:计算的是前面的元素比后面的元素的2倍大的个数。计算翻转对与合并分开写。
2024-10-21 19:42:55 942 5
原创 【刷题11】分治—快速排序
思路:建立一个小堆,先放k个元素,然后遍历剩余的元素,只要比堆顶大就进堆,往下沉。最后的堆顶就是第k大的元素。思路:快速排序—与前面相同,最后返回前cnt个元素。思路:快速排序(三路划分)
2024-10-18 14:48:08 394
原创 【刷题9】位运算专题
题目:使用STL的排序算法进行排序,只要是重复的字符必定是挨在一起的,所以可以遍历数组,有出现连续相同的字符就是有重复的代码:解法二:数组定义一个数组,大小26初始化为0,字符串的字符相对映射填入数组中,每个位置表示出现的次数,大于1次就说明有重复代码:解法三:位运算如果字符串的长度超过26个,必定有重复的,直接返回false定义的一个整型变量bitmap,它的比特位就是位图。如果位图的某一位已经存在,就返回false,否则填入位图中。遍历整个字符串后返回true代码:三、丢失的数字题
2024-10-12 18:34:12 812
原创 【刷题7】寻找数组的中心下标、和为k的子数组、和可被k整除的子数组
除自身以外数组的乘积>根据本题变形。思路:前缀和+哈希表。思路:前缀和+哈希表。
2024-10-09 21:00:07 307
原创 【刷题6】一维前缀和、二维前缀和
四、多开一个好放数据,同时满足l、r下标刚好对应上。一、前缀和,时间复杂度O(1),快速得到区间的值。三、使用前缀和,根据题目计算出区间。二、预处理,公式——一、预处理前缀和矩阵。
2024-09-30 23:47:04 324
原创 【刷题5】在排序数组中查找元素的第一个和最后一个位置
细节2:如果找完左端没有left=nums[mid],也是直接返回-1-1。,一旦相等就会死循环。或者说left=right就终止了。细节1:如果数组没有元素,直接返回-1-1;返回begin和end,是。取中点问题:取第二种。
2024-09-27 21:14:08 327
原创 【刷题4】最小覆盖子串
返回值:定义返回值ret,在判断里面截取字符串tmp,这里需要一个临时的字符串str,每次截取后赋值给str,然后如果ret为空,str直接给ret;ret不为空,比较ret和str的长度,只有str的长度小于ret的长度,才把str赋值给ret。定义变量count,统计有效字符的个数,用法与上一篇博客的两题一样,先进窗口,再判断count++;先判断count–,再出窗口。计算两个字符串的长度,定义两个哈希表,用其中一个哈希表先统计字符串t的字符出现个数。判断条件:count == 字符串t的长度。
2024-09-26 20:49:24 320
原创 【刷题3】找到字符串中所有字母异位词、串联所有单词的子串
哈希表2统计字符串p的每个字符出现的个数,然后遍历字符串s,先进窗口,相同的映射位置,哈希表1该位置的个数<=哈希表2的个数,count++(比目标数小才要++,超过了就不需要++,有等号是因为先进窗口)。如果超过固定长度,先判断哈希表的位置,哈希表1该位置的个数<=哈希表2的个数,count- -(比目标数大去掉也无效,小于了有效数就减少,等于是因为先判断的,后面要哈希表位置要减减),然后出窗口。循环次数:是单词的个数(每个单词的个数是相同的)固定窗口大小:words的长度 * 单词长度。
2024-09-25 21:18:24 278
原创 【刷题2—滑动窗口】最大连续1的个数lll、将x减到0的最小操作数
要让操作数的次数最小,就要让等于target的子数组尽可能大,然后用滑动窗口的思路做,返回值为:如果子数组中没有和等于target就返回-1,否则返回数组长度减去len(n-len),得到最小操作数。最右边和最左边的和为x,用一个变量sum统计数组所有的元素之和,sum-x就是剩下区域的元素,这个区域是连续的,可以用滑动窗口。要考虑target是负数的情况,如果是负数,直接返回-1,因为数组的每个元素都是整数。问题转换为:找到一个最长子数组,这个数组里面0的个数不能超过k个。
2024-09-23 21:22:50 427
原创 【计算机网络】传输层协议TCP
因为在前面两次的握手中,客户端发送信息,建立连接,服务端应答,客户端收到服务端的应答,才确定之前发送的信息服务端是收到。在数据传输的时候有建立连接的报文、正常通信的报文、断开连接的报文,总之就是通信过程中会收到各种各样的报文,而TCP报文是需要类型的,所以要区分报文的类型,标志位存在的意义就是区分不同的TCP报文类型。在等待的过程中,接收端的接收缓冲区里面的数据更多交给上层处理,即接收缓冲区空间更大了,这时再应答既可以确认前面的收到的信息,又能通知发送端可以发送更大的信息,提高了发送效率。
2024-09-23 18:21:10 1611 14
原创 【刷题—双指针】复写0、三数之和、四数之和
定义两个变量cur等于0,dest等于-1,让cur去遍历数组。如果cur指向的元素是0,dest往后两步,非0,往后一步。判断dest的位置,如果大于等于n-1,就停止操作,否则cur++
2024-09-21 21:37:50 365
原创 【计算机网络】传输层协议UDP
端口号标识一个主机上进行通信的不同的应用程序。IP+端口号就能确定互联网中的唯一进程。可以,一个进程可以有多个服务,比如tcp、udp,两个分别有各自的端口号,可以找到对应的客户端。不能,因为端口号是用来确定一个主机上的唯一一个进程,如果可以被多个进程绑定,就不具有唯一性。有些服务器是非常常用的,为了使用方便,人们约定一些常用的服务器,都是用以下这些固定的端口号。:应用层给多少,UDP发送多少,既不会拆分,也不会合并。一个进程是否可以 bind 多个端口号?一个端口号是否可以被多个进程 bind?
2024-09-20 16:06:40 1033
原创 【计算机网络】应用层序列化
用户在主机A发送消息给另一个用户主机B,消息序列化后通过系统调用到发送缓冲区,然后经过网络的每个分层到另一个主机,再自底向上到接收缓冲区,然后通过系统调用到应用层,再序列化变成用户可看到的消息。注意:系统调用让数据从用户层到发送缓冲区,或者从接收缓冲区到用户层,这个过程都是拷贝。用户发送一段数据先到C缓冲区,然后通过系统调用交给操作系统的管理区,发送的数据到task_struct,根据fd在文件描述符表找到位置,再指向指定的struct file,然后把数据传输到缓冲区,缓冲区会把数据刷新到磁盘中。
2024-09-15 17:37:25 1051
原创 【计算机网络】网络基础
到了数据链路层,封装了源mac地址和目的mac地址,这两个是会变化的,当前的源mac地址是A,目的mac地址是left,路由器其中的一个子网的数据链路层。路由器知道用户A要给用户B发信息,所以路由器的另一个子网与用户B联系,对源IP和目的IP地址重新封装,源mac地址和目的mac地址就发生了变化,源mac地址是right,mac地址是B,然后交给用户B,最后逐层向上解包与分用,用户B获取信息。TCP/IP协议栈是C语言编写的,双方传输使用的是同样的数据类型,所以,经过网络,双方一定能识别对方的信息。
2024-09-11 21:00:45 1504 7
原创 【Linux操作系统】线程的互斥与同步
总之就是两个人要竞争一把锁,如果拿苹果的人竞争性更强,每次都是他申请到锁,放苹果的人就没机会放苹果了,这也导致拿苹果的人每次申请到锁后去盘子上总是没有苹果拿,但是他又一直占用锁(每次申请到锁的都是他),所以放苹果的不能申请到锁放苹果,拿苹果的在盘子上也没有苹果拿,这就导致整个过程很不合理。又来了个线程2,此时线程1切换为线程2(注意:CPU执行线程1时是可以随时被切换的),线程1要带走寄存器中的1,然后线程2把0带入到寄存器中,再与内存的数据作交换,还是0,说明锁被其他线程占用,线程2就会挂起等待。
2024-09-06 14:25:55 875 9
原创 【Linux操作系统】线程控制
而线程也要到内存中读取,但是在CPU中,有一个硬件设备叫cache,作用是可以将当前读到的代码的周围其他代码和数据也一并交给CPU,这样下次遇到时,就可以直接在CPU处理了,效率提高了一些,工作也就少了。线程不一样是因为多个线程在一个进程内部,每个线程是一个进程的其中一个执行流,进程的所有资源(地址空间、页表、内存)都是可以给这些线程共享的,所以线程切换时,cache里面的上下文数据还在。线程分离了,但是资源依然是共享的,主线程先退出,那么整个进程就会结束,分离的线程也同样退出。
2024-09-05 08:42:44 1063 8
原创 【Linux操作系统】线程概念
对于进程,比较老的说法是加载到内存的程序叫做进程;修正后的说法是进程 = 内核数据结构 + 程序的代码和数据。对于线程,它是进程内部的一个执行分支,是CPU调度的基本单位。在地址空间的正文代码区,用户写的代码在进程中,都是串行执行的。换句话说,如果还有其他的进程(有多个进程),那么还需要开辟空间给新的进程创建地址空间和页表。这样就比较浪费时间和空间,即成本高。
2024-09-04 11:22:37 600
原创 【Linux操作系统】信号产生
2号信号是终止进程,用户可以让它的处理方式通过函数变成打印一句话和终止进程,终止进程的退出码为100,再把函数给系统调用接口signal。设置一个简单的闹钟,接口alarm,注意,闹钟设置的时间只是什么时候响,但是只响一次。2、信号到来时,如果此时有更重要的事情要处理,那么到来的信号要临时保存,即在合适的时候处理;4、信号的产生,是由别的进程产生的,当前的进程收到这个信号之前,在做其他的事情,是并发的。3、信号的产生是随时的,不能准确预料,所以信号是异步发送的;默认,就是按原来信号的处理方式进行处理。
2024-09-02 12:02:27 786
原创 【Linux操作系统】进程间通信(2)——共享内存
shmflg有3种,IPC_CREAT:如果共享内存不存在,就创建,如果已经存在,就获取它;使用共享内存,一定是一个进程创建共享内存,另一个进程获取。共享内存如果我们没有主动释放,它就会一直存在,因为共享内存是随系统的,除非重启系统,否则一直存在。ftok的参数由用户提供,通信的两个进程都是同样的pathname和proj_id,这样返回的key是相同的,使用的就是同一个共享内存了。进程A把它的数据在地址空间中通过页表映射到物理内存中,进程B通过页表获取物理内存的物理地址,得到数据。
2024-08-27 10:14:32 345 7
原创 【Linux操作系统】进程间通信(1)
既然有创建子进程,就是要子进程办事的,如果让子进程w,父进程r,那么,子进程写的通过缓冲区刷新到磁盘文件中(写的时候,文件要先被加载到内存,即缓冲区,),然后,父进程通过缓冲区读取文件的信息(也是在缓冲区,即内存中。五、管道只能单向通信。父进程最开始时的权限是rw,因为这样给子进程也是rw,然后关闭权限(父进程关闭w,子进程关闭r,注意,父进程刚开始不能只有一个r或w,因为不能新打开权限),一个读,一个写。也就是说它会有一块内存,但是与磁盘无关,它是一个内存级文件,没有名字,是匿名的,一般就叫它——管道。
2024-08-23 19:41:47 939 9
原创 【Linux操作系统】基础IO
目录一、接口使用1.1 铺垫知识1.2 C接口使用1.3 系统接口使用二、认识fd三、缓冲区四、文件系统五、软硬连接六、动静态库6.1 静态库的制作和使用6.1 动态库的制作和使用七、理解动态库加载一、接口使用1.1 铺垫知识文件=文件内容+文件属性 。一个文件如果它的文件内容为空,并不代表它没有占用内存,因为它的文件属性也是要占内存的,比如文件名、文件类型、文件权限等。访问文件前,文件必须被打开,必须加载到内存中。修改文件,都是通过执行代码的方式进行修改,也就是执行这个代码的程序运行起来。是进
2024-08-20 15:19:53 964 9
原创 【Linux操作系统】进程控制
fork之后,子进程是被按照以父进程位模板创建的,所以地址空间和页表是以拷贝发方式给子进程,父子进程的虚拟地址是相同的,页表也是,在没有对一方进行写入的情况下,默认子进程的地址空间的虚拟地址通过页表指向的是前面父进程在物理内存中开辟的代码和数据,所以父进程和子进程共享代码。子进程被创建时它的页表指向的代码和数据和父进程是一样的(默认情况下),但是要进行程序替换,此时内存中发生写时拷贝,不仅数据拷贝了,代码也拷贝了,父进程还是原来的代码和数据不影响,子进程的代码和数据被其他程序替换了。可以使用echo $?
2024-08-20 09:00:25 722 8
原创 【Linux操作系统】进程概念
常见的说法中,有:加载到内存中的程序是进程或者正在运行的程序是进程。程序要先加载到内存中去,而且不一定只有一个程序,可以有多个程序加载到内存中。多个程序加载到内存中,那么操作系统要对它们进行管理,管理方式是:先描述,再组织。先描述:某一程序加载到内存中,操作系统首先是对它的属性信息进行描述,有:每个加载到内存中的程序都要有这样的描述,这个描述的结构体对象叫做PCB,process ctrl block进程控制块。所以PCB是什么?是描述进程的属性信息的结构体对象。为什么要有PCB?
2024-08-16 12:57:06 1037 7
原创 【C++】智能指针
两个节点的资源没有被释放,因为循环引用的问题。初始化两个节点时,各自的引用计数为1,然后node1的next指向node2,使node2节点引用计数变成2;因为node1->_next = node2和node2->_prev = node1时,weak_ptr的_next和_prev不会增加node1和node2的引用计数,所以只要有引用计数变成0,就能释放资源了。它可以用一个对象管理一份资源,在对象构造时获取资源,对象析构时释放资源,并且在对象的生命周期中始终可以使用资源。这种方法其实也不行。
2024-05-19 13:32:07 1101 21
原创 【C++】异常
实际使用中很多公司都会自定义自己的异常体系进行规范的异常管理,因为一旦有人随意抛异常,就不好了。所以实际中都会定义一套继承的规范体系。这样大家抛出的都是继承的派生类对象,捕获一个基类就可以了。////......_id是编号,_errmsg是具体错误信息。what()函数返回错误信息,记得要加上virtual,形成多态。
2024-04-12 20:11:34 1150 30
原创 【C++】lambda表达式
以上代码虽然可以实现自定义类型中的某个成员的比较规则,但是这样写是不是有些麻烦,每次实现一个algorithm算法,都要重新去写一个类,如果每次比较的逻辑不一样,还要去实现多个类,特别是相同类的命名,这些都给编程者带来了极大的不便。这段代码捕捉列表后面要有小括号和mutable,因为捕捉列表里的a和b是常属性的,带上mutable可以取消常属性,有mutable不管有没有参数都要加上小括号。函数对象,又称为仿函数,即可以像函数一样使用的对象,就是在类中重载了operator()运算符的类对象。
2024-04-09 12:40:58 2367 12
原创 【C++】哈希之布隆过滤器
一种支持删除的方法:将布隆过滤器中的每个比特位扩展成一个小的计数器,插入元素时给k个计数器(k个哈希函数计算出的哈希地址)加一,删除元素时,给k个计数器减一,通过多占用几倍存储空间的代价来增加删除操作。k为哈希函数的个数,这里有3个哈希函数,m为布隆过滤器的长度,n为插入元素的个数,ln2的大小约为0.69,推导出:4.34 * n = m,简化一下m与n的关系为:5n = m。插入元素时,不同的哈希函数计算出该元素的不同的映射位置,然后将要映射的位置标记为存在,即比特位为1。
2024-04-06 15:22:50 1125 8
原创 【C++】学习多态原理
用基类对象去调用,派生类对象给基类对象是切片,但注意:这过程中有拷贝构造出一个基类的对象,这个基类的对象所对应的虚表是基类的虚表,结果导致拷贝构造的基类对象都去基类对象的虚表中找虚函数,就没有调用派生类对象的虚表中的虚函数了。因为派生类继承基类得到基类的那部分的虚表,虚表里面的虚函数地址是基类的,如果不进行重写,在派生类对象的虚表中找到的虚函数依然是基类的,所以要对基类的虚函数进行重写,虚表中也同时完成了虚函数地址的覆盖,调用时就是派生类的了。注意:同一个类的对象,对应的是同一张虚表。
2024-04-05 14:47:10 802 7
原创 【C++】哈希之位图
一个整数等于32个比特位,根据位图的概念,用每个比特位是1还是0来确定一个数到底在不在,1个整数的32个比特位可以用来确定32个数据的存在,所以16G除以32等于0.5G,即512M,这就是开辟的空间大小,是不是节省多了。类的模板是非类型模板参数,传的是数据的大小。一个二进制比特位只有两种状态,要么为0,要么为1,如果某个数据在,则对应映射的比特位为1;每个数都有对应映射的比特位,将这个数除以32找到该数在数组中的位置,取模32找到映射的第几个比特位,1左移前面取模的位数,然后按位或将该比特位设置为1。
2024-04-02 21:47:35 1212 6
原创 【C++】新的类功能和可变参数模板
empalce系列中的emplace_back函数与push_back函数的功能是相同的,都是尾插数据。只需在该函数声明加上=delete即可,该语法指示编译器不生成对应函数的默认版本,称=delete修饰的函数为删除函数。对于深拷贝类对象,如果插入的是类对象时,两个没有区别;如果插入的是对象的参数,那么emplace系列函数会。对于浅拷贝类对象,如果插入的是类对象时,两个没有区别;如果插入的是对象的参数,那么emplace系列函数会。很明显是不行的,因为模板是编译时解析,for循环是运行时解析参数。
2024-04-02 12:38:10 656 8
原创 【C++】右值引用
引用是给对象取别名,本质是为了减少拷贝。以前我们学习的引用都是左值引用,右值引用是C++11新增的语法,它们的共同点都是给对象取别名。既然如此,有了左值引用,为什么还要有右值引用?右值引用具体是怎样的?以及它有哪些应用场景?接下来,会详细分析~~左值是一个表示数据的表达式,可以是变量名、解引用的指针和前置++。左值可以取地址和赋值,它出现在赋值符号的左边。如果定义的左值被const修饰,那么它就不能被赋值,但是可以取地址。//左值int a = 10;
2024-03-31 09:45:17 1207 31
原创 【C++】用哈希桶模拟实现unordered_set和unordered_map
顺序结构中(数组)查找一个元素需要遍历整个数组,时间复杂度为O(N);树形结构中(二叉搜索树)查找一个元素,时间复杂度最多为树的高度次logN。可以不经过任何比较,一次直接从表中得到要搜索的元素。构造一种存储结构,通过某种函数使元素的存储位置与它的关键码之间能够建立一一映射的关系,那么在查找时通过该函数可以很快找到该元素。主要有3种操作:插入——根据待插入元素的关键码,以此函数计算出该元素的存储位置并按此位置进行存放查找。
2024-03-24 18:22:09 1457 27
原创 【C++】用红黑树模拟实现set、map
set、map的底层结构是红黑树,它们的函数通过调用红黑树的接口来实现,红黑树一些接口需要通过树形迭代器来实现。set是k模型,map是kv模型,红黑树要不要写两份呢?答案是不需要,只用一份即可,通过仿函数来控制。T _data;,_col(RED){}红黑树有3个指针域,数据域用T来表示,如果是set,那么传过来的是k模型;如果是map,是kv模型。新增的节点的颜色默认是红色(根节点除外)。
2024-03-19 20:51:55 1103 22
原创 【C++】实现红黑树
红黑树也是三叉链结构(左指针、右指针和父亲指针),有一个新的存储位来记录节点的颜色,这里实现的红黑树是kv模型。RED,//红色BLACK//黑色,_kv(kv),_col(RED)//默认的新节点都是红色的{}
2024-03-15 21:00:48 1267 21
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人