自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

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

原创 算法:常见位运算技巧总结

按位与 & :有0为0,无0为1按位或 | :有1为1,无1为0按位异或 ^ :相同为1,不同为0按位取反 ~ :0变成1,1变成0左移 << : 二进制序列向左移右移 >> :二进制序列向右移。

2024-10-29 23:11:42 232

原创 数据结构:并查集

在一些应用问题中,需要将n个不同的元素划分成一些不相交的集合。开始时,每个元素自成一个单元素集合,然后按一定的规律将归于同一组元素的集合合并。在此过程中要反复用到查询某一个元素归属于那个集合的运算。适合于描述这类问题的抽象数据类型称为并查集(union-findset)。举个例子看看比如:某公司今年校招全国总共招生10人,西安招4人,成都招3人,武汉招3人,10个人来自不同的学校,起先互不相识,每个学生都是一个独立的小团体,现给这些学生进行编号:{0, 1, 2, 3,

2024-10-29 22:07:14 842

原创 算法:利用前序序列和中序序列构造二叉树

所以,我们需要一个变量i来遍历前序序列,注意,在递归中,我们需要引用或者指针来传递该参数。可以通过中序遍历去分割二叉树,将二叉树分割成 左子树 根 右子树。前序遍历的顺序是:根 + 左子树 + 右子树。中序遍历的顺序是: 左子树 + 根 + 右子树。找到根节点之后,在中序遍历中去寻找这个根节点,就可以将中序遍历分成三段了。后序遍历的顺序是 左子树 + 右子树 + 根。所以,我们可以通过前序遍历获得二叉树的根。

2024-10-28 22:21:40 594

原创 数据结构:二叉树的非递归遍历

在前面我们学习了二叉树的递归遍历,但是,众所周知,递归是比较消耗资源的,所以,在有些注重性能的地方,会需要使用到非递归遍历,在这里介绍一下,二叉树的非递归遍历。本质上:二叉树的非递归遍历也是模拟递归遍历,递归遍历中需要产生深层次的函数栈帧,而非递归就是将这些深层次的函数栈帧存起来模拟递归。

2024-10-28 22:00:44 566

原创 算法:KMP算法详解

BF算法即暴力求解字符串匹配的算法面对这样两个字符串,BF算法就是用两个指针,一个i,一个j,分别从s和t的开始位置开始依次匹配当遇到s[i] == t[0]的时候,此时有可能字符串匹配,需要进行检查于是从i开始,依次比较i后面的元素和t中的元素,如果恰好完全相等(次序,字母都相同),则返回i的下标即可如果遇到了s[i]!= t[j],则说明此处不匹配,i需要回退到比较前的i的下一个位置,j需要回退到0,重新开始进行比较。

2024-10-22 10:57:22 1042

原创 数据结构:红黑树

前面我们介绍了AVL树来解决搜索二叉树不平衡的问题,今天我们带来一种新的解决方案,同时,这种解决方案在实践中比AVL树更常用,这种数据结构就是红黑树。

2024-10-13 11:57:30 1703

原创 算法:525.连续数组

在该题中,要寻找一个连续子数组,使得其中含有相同数量的0和1,0变成-1之后,也就是,含有相同数量的-1和1,也就是我们需要再 [0 , i - 1] 这个区间里面寻找一个最短的前缀和等于 sum - 0。在处理二进制数组的时候,因为数组里面只有0和1,我们可以将所有的0变成-1。这个时候1和-1之间就可以产生很多抵消,有利于处理数组。处理的大体思路类似,依旧采用前缀和+哈希表来处理。分析到这里,相信读者可以联想到前面的一道题。在这道题目里面就是和为0的子数组。那么这个区间的和就是0。

2024-10-13 09:31:42 564

原创 算法:974.和可以被K整除的子数组

然后在[0,i-1]区间内去hash表中寻找一个区间的前缀和对k取模的结果与sum对k取模结果相同即可。将sum% k的余数放到hash表中(一定要是先查找在插入)(2)对于[0 , i]区间的和正好是K的倍数的情况如何处理。还是一样,我们先去把余数0提前先往hash表里插一个即可。按道理来说应该是3,但是C++/java里的答案是-2。OK,到这里前置知识讲完了,我们就正式开始讲思路了。那么只需要找两个区间的前缀和对k取模的余数相同即可。需要找一个子数组的和是k的倍数。记录sum % k的余数。

2024-10-12 11:00:30 431

原创 算法:560.和为k的子数组

这道题目也是要求我们求一段连续区间的和,我们的前缀和算法也能帮助我们做到 [l , r] = dp[r] - dp[l - 1]如果开前缀和数组的话,那也是需要遍历前缀和数组,以每一个下标为终点当sum去找sum - k,时间复杂度依旧是O(N。抽象来看,存在一个区间的和为k,那么在==[0 , i - 1]==就存在一个前缀和为sum - k。所以,我们求区间和为k,也就是,k = sum[r] - sum[l - 1]nums[i]可正可负,区间的和没有单调性,使用不了滑动窗口。这里带来新的解决方法。

2024-10-12 10:43:54 744

原创 算法:238.除自身以外数组的乘积

另外,这道题目对边界的情况处理不一样。而不能像前缀和和后缀和中一样处理成0。这道题目的区别在于,这道题是预处理。724. 寻找数组的中心下标。在前一篇博客讲解了该题目。

2024-10-08 22:55:13 475 1

原创 算法:724.寻找数组的中心下标

那么我们可以借助前缀和思想,将[left]区间和[right]区间的元素和求出来,就可以很好的方便比较。我们只需要[left]区间内的元素和等于[right]区间的元素和即可,此时mid就是中心下标。看到这里,读者们可能会问,通过前缀和算法为什么可以求出[right]区间的和呢?最后处理好前缀和数组和后缀和数组之后,只需要遍历比较前缀和数组和后缀和数组即可。当然,用整个数组的和减去[left]区间和mid元素可以得到答案,顾名思义,将前缀和反过来,我们从数组末尾向前求和就成了后缀和。什么是后缀和算法呢?

2024-10-08 22:47:52 264

原创 算法:前缀和算法模版

当我们需要求区间[l,r]的元素和的时候,就可以用dp[r] - dp[l - 1]我们先预处理出来一个dp数组,用来存放从[1,1]到[i,j]这个矩阵内的元素和。我们可以用递推的思想,前n个元素的和等于前n-1个元素的和加上第n个元素的和。我们可以预处理出一个dp数组,来存放[1,i]的区间的元素和。那么A+B+C+D = (A+B)+(A+C)- A + D。很容易想到的是,(A+B+C+D) - (A+B+C)来,我们抽象出来一个矩阵,从[1,1]到[i,j]诶嘿,来,试试小学几何题常用的割补法。

2024-10-08 22:18:34 908

原创 算法:LCR 173. 点名 (原:剑指 offer:0~n-1 中缺失的数字 )

求出每一个元素与前一个元素的差,然后哦遍历这个差,当发现差值不等于1的时候,就返回该位置的值即可。利用高斯求和公式求出0~n的和,然后减去nums数组中的每一个数,最后的结果就是缺失的数字。注意了,这是因为题目特殊,题目是有序的情况下,才能存在这种二段性,否则要先排序。将0~n的所有数字均与nums中的数字按位异或一下,最后的结果就是缺失的数字。我们可以发现,当有序的序列缺失了一个元素之后。在缺失元素之前的每一个元素都和下标相等,采用按位异或的操作,相同为0,不同为1。时间复杂度,O(N)

2024-09-30 22:17:54 564

原创 算法:153.寻找旋转排序数组中的最小值

while(left < right) //这里不能取等,不然死循环。题目要求O(logN)的时间复杂度,那就必然是使用二分算法了。题目要求返回最小元素,不是最小元素的下标。根据这一规则,二分不就来了嘛。很明显,是寻找左边界的二分。首先,我们来寻找二段性。

2024-09-30 21:35:31 418

原创 算法:852.山脉数组的峰顶索引

题目的提示已经非常明显了,使用O(logN)的算法,那就是二分算法。观察数据,可以发现,需要找的峰顶索引的左右两侧数据有不同的特征。根据此二段性,我们就可以设计出二分算法了。峰顶索引左边的数据都比前一个数据大。峰顶索引右边的数据都比前一个数据小。

2024-09-29 22:00:37 441

原创 数据结构:AVL树

/左子节点//右子节点//父亲节点//数据//平衡因子:_kv(kv){}注意:AVL树使用三叉链实现,多了一个parent指针,用来记录父亲节点,方便使用。

2024-09-29 21:51:54 967 3

原创 算法:69.x的平方根

3、right - left + 1,因为这里出现了 + 1,所以可能超出int的范围,所以left就不从0开始,从1开始即可,对0进行特判即可。1、这里使用的是寻找右边界的二分算法,left < right , mid = left + (right - left + 1) / 2;2、target的范围是int,但mid * mid可能超出int的范围,需要把mid设置成long long类型。序列,我们可以发现分成两部分,一边 <= target,另一边大于 target,我们先用暴力查找找点灵感。

2024-09-24 22:02:42 382

原创 数据结构:搜索二叉树

在前面我们已经学习了二叉树的基础操作,但是,仅仅是二叉树,没有太大的作用啊,存数据效果没有顺序表和链表好,那为啥还要学二叉树呢?这不就来了嘛,给二叉树增加一些性质,作用不就出来了嘛。本篇文章将介绍二叉树的进阶版本,给二叉树增加了搜索特性,搜索二叉树。

2024-09-24 11:45:13 1093 1

原创 数据结构:二叉树OJ题(基础版)

更完两期二叉树的知识之后,来做几道oj题巩固一下基础。

2024-09-22 21:15:41 1060 1

原创 数据结构:二叉树(2)

普通的树的实用价值比较小,将树更一步特殊化成二叉树,将获得更多的特殊性质。例如搜索二叉树,红黑树等。这篇博文主要介绍二叉树的基础知识,进阶版高级二叉树,后续会持续更新。

2024-09-21 11:28:16 1301

原创 数据结构:二叉树(一)

ps:偷懒了几天,接着更新。

2024-09-21 10:31:40 1007

原创 算法:76.最小覆盖子串

问题来了,该题目需要大量使用hash表比较,这是时间复杂度很高的,并不是和好,怎么去优化呢?利用hash表统计窗口内的个字符出现的个数,与hash1进行比较。令t用的hash表为hash1,s用的hash表为hash2。而不要在过程中,每一次更新结果的时候都创建一个子串。这道题,最后要求我们返回的是子串,而不是下标,一定要设置一个begin和len来标记子串,还是老样子,连续问题,滑动窗口+哈希表。样例里面有内存特别大的极端样例。选取符合情况的最小子串即可。注意,这里有一点比较坑。详情见异位词的那道题。

2024-09-16 20:01:43 609

原创 算法:30.串联所有单词的子串

我们这么来看这道题目,我们把words数组里面的字符串都看成一个字母,那这个题目不就是让我们去在s字符串中去寻找words数组的异位词吗?在s中寻找的时候,可能bar一组,也可能arf一组,也可能rfo一组,情况非常多。注意:这道题目中words数组里面的字符串长度都是相同的,不妨令长度为len。当count==words.size(),此时的left即为有效下标。但是,不要忘记了,words数组里面的字符串长度是相同的,这道题目类似寻找异位词的题目,我认为是寻找异位词的升级版。出窗口前维护count。

2024-09-16 19:24:23 468

原创 算法:TopK问题

有10亿个数字,需要找出其中的前k大个数字。为了方便讲解,这里令k为5。

2024-09-15 19:12:48 691

原创 数据结构:堆排序

更完堆,再更一期堆排序。

2024-09-15 13:06:21 1230

原创 数据结构::堆

1.下列关键字序列为堆的是:()答案:A。

2024-09-14 21:25:40 1315

原创 一道迭代器失效练习题

首先学习迭代器失效学完迭代器失效之后做一道题呗。

2024-09-10 20:35:33 304

原创 438.找到字符串中所有字母异位词

注意,这里hash表里面仅仅存的是字符,总共26个小写字母,直接遍历一遍出结果就可以,还是很好比较的,但是,如果存的不是字符呢?出窗口前,发现hash2[left] == 2 > hash1[left],那么说明出的这个元素是无效元素,count不需要改变。开始 hash2[s[right]] 进入hash表后,1 <= hash1[c],那么这就是有效元素,count++下一次出窗口时,发现hash2[c] <= hash1[c],诶,就是有效元素了,count–这是再遍历hash去比较,比较的麻烦。

2024-09-10 18:39:28 1039

原创 102.二叉树的层序遍历

单纯层序遍历使用队列就可以了,每次出队列的时候,进行输出,并将该元素的left和right入队列即可。二叉树的单纯层序遍历还是很简单的,但是这个题,要求我们将返回值按层写到一个二维数组中,该如何实现呢?经过观察,可以发现,每一次删完一层的元素之后,队列里面剩余的元素个数就是下一层的元素个数。解决完关键问题之后就比较简单了,套上一般层序遍历的代码来写即可。我们可以设置一个变量来记录每一层的元素个数。再来一个queue存每一个元素的层数。在这个题目中,问题在于,

2024-09-09 20:08:36 291

原创 946.验证栈序列

我们知道一个栈的一种入栈顺序可能对应多种出栈顺序,让我们肉眼来判断一下,还是很容易判断出来是不是正确的出栈顺序,那么如何用代码来实现呢?pushed走完了之后,去查看s是否为空,如果s为空,说明匹配上了,否则,不匹配。先把pushed进一个栈s,然后比较s.top 与 popped[i],++i后再与s.top继续比较,直到不相等跳出循环。如果相等,就s.pop,同时++i;如果不相等,就继续将pushed入栈。OK,先掏一个栈s出来再说。

2024-09-09 19:52:31 292

原创 147.最小栈

mins.top一定是最小元素,所以s.top 不可能 < mins.top。其中一个栈s实现栈的基本功能,另一个栈mins实现检索最小元素的功能。在每一次入栈的时候,都将该元素x与mins栈的栈顶元素top相比较。注意这里要加上等号,因为,可能会有多个最小的元素,比如出现多个0等。这道题目做起来还是比较简单的,使用两个栈就可以实现题目要求。来看一下怎么样实现检索最小元素的功能呢?x入mins栈,此时x也就成了最小的元素。将s.top 与mins.top进行比较。也就是最小元素,此时两个栈同时pop。

2024-09-09 19:37:08 542

原创 904.水果成篮

出窗口:hash[left]–的同时,要去判断是否hash[left] == 0,如果等于0,删除该元素即可。更新结果,ret = max(ret,right - left + 1),使得这个子数组里面最多存在两种不同的数字,很容易联想到使用滑动窗口。另外,需要使用hash表来记录区间内的不同种水果的个数。判断:哈希表的size > 2,就需要出窗口。读完题目,很明显,这个题目需要我们寻找一个。首先还是left,right = 0;进窗口:right进哈希表。

2024-09-08 20:23:05 365

原创 1658.将x减到0的最小操作数

题目要求从最左边或者最右边移除元素,需要思考两侧,这是比较麻烦的。3、最后的返回值,要用size - len,别直接返回len。1、可能原数组的和 <= x,这是要进行特殊判断的。2、确定好如何进窗口,判断,出窗口,更新结果。很明显,使用滑动窗口可以很快速的解决这道题。区间,所以,这个题目可以转化成寻找一个。,使得子数组的和为原数组的和减去x。一下,最后剩余的元素是不是中间的。

2024-09-08 20:11:30 498

原创 C++:浅谈双向迭代器--以list迭代器为例

这篇文章实际上我感觉还是没有讲清楚,有问题的话,还请读者在评论区指出。迭代器主要是分为随机迭代器和双向迭代器。随机迭代器由于在物理空间上是连续的,所以支持++,–,+,-,>,<,+=,-=等操作。双向迭代器在物理空间上不连续,不能够支持+,-,>,<,等操作,但支持++,–。这篇文章主要讲解双向迭代器如何在物理空间不连续的情况下实现迭代器的通用功能。本文以list容器为例。这篇文章实际上我感觉还是没有讲清楚,有问题的话,还请读者在评论区指出。

2024-09-08 14:22:11 764

原创 1004、最大连续1的个数III

当0的个数大于k时,就需要出窗口了,记录下此时的长度,需要将left跳过一个0,继续寻找新的窗口。该题,最大的难点在于,如何将“翻转最多k个0”转换成比较好做题的语言,当0的个数小于等于k时,可以继续扩大窗口,right++;还是设置left和right两个指针,从0开始移动,另外设置一个变量zero来统计窗口内0的个数,与下面这个题很像,就不详细解释了。这样的话,就更好理解了。

2024-09-05 21:09:47 355

原创 3、无重复字符的最长子串

注意,在出窗口的时候,需要删除重复字符前面的字符,否则,这些字符,在后面新子串里面也会被当做重复字符。当hash表里面没出现right字符时,就插入hash表,right++,增加子串的长度。当hash表里面right字符出现的次数不是大于1的时候,就出现了重复,需要出窗口了。为了去判断窗口里面有没有出现重复的子串,可以使用一个hash表来存出现的次数,这时,我们将left移到重复字符的下一个位置,继续寻找更长的子串。子串是连续的,很容易联想到滑动窗口,处理连续子串问题很方便。记录下此时子串的长度。

2024-09-05 20:50:55 548

原创 209.长度最小的子数组

随着left和right的移动,left和right之间就夹出了窗口。进窗口,判断,出窗口,以及更新结果,更新结果的步骤根据不同的情景有不同的变化,前三个步骤一般都会有。首先,子数组是连续的,第二,所有的元素都是正整数,所以子数组的和具有单调性。可以通过++left来缩小窗口(出窗口),直到sum < target。说明和太小了,需要继续扩大窗口,于是right++,继续处理(进窗口)我们再设置一个sum变量,来统计窗口之间的和的大小。和的大小达到了要求,这时候就需要去寻找最小的窗口。

2024-09-05 20:35:56 353

原创 18.求三数之和

不妨将target固定位最大值,将需要的两个数在target的左边区间进行寻找,即在小于target的范围里寻找,这时利用双指针,记作left,right,从两侧向中间逼近即可。,所以,我们可以在找到了符合要求的三元组后,跳过相同元素再继续寻找,这样,就可以避免重复的三元组。这道题目有一点很坑的地方,题目中target是int类型,但是四数之和有可能是超过int类型的范围的,需要强转。我们先固定一个数,记作target,则只需要寻找两个数,使这两个数的和为负target即可。符合要求,保存下来,继续寻找,

2024-09-04 21:04:51 505

原创 611.有效三角形的个数

设置left和right两个指针,left指向左边,right指向距离大边最近的一条边,依次向中间汇合,进行调整,即可得到答案。但是,如果已知三条边的大小关系,只需要两条较小边的和大于第三条边即可。则,所有left右边的边都可以和right和target构成三角形,则,所有right左边的边都不能喝left和target构成三角形。所以,我们需要首先进行排序来获取不同边的大小关系。left++继续寻找该target下的有效三角形。我们如何寻找两条较小边和一条大边呢?不妨先固定一条大边,移动两条小边。

2024-09-03 18:50:20 419

原创 VS2022出现C1001内部编译器错误的情况分析

今天在写类模板的时候,将声明和定义全部在.h文件中编写,但是由于一些低级失误,出现了这个报错,也是第一次遇见,花了很长时间才发现自己犯得低级失误,发出来,以防大家也发生类似的错误。

2024-09-03 13:54:43 454

空空如也

空空如也

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

TA关注的人

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