
算法题
文章平均质量分 77
算法讲解
23级二本计科
这个作者很懒,什么都没留下…
展开
-
floodfill算法_dfs
对靠近Pac洋的格子dfs进行标记,还要对靠近Atl洋的格子dfs进行标记。边界情况:如果初始位置值结束目标值,那在dfs过程中不会改值,就会出现走重复路径的情况。每遍历到一个1且没有标记过,就从该位置进行dfs,进入dfs就标记并记录当前面积,dfs结束获取这一块1的面积。1.看临边是Pac洋的格子从低到高走,四周的格子比它大就可以走。2.看临边是Atl洋的格子从低到高走,四周的格子比它大就可以走。(用红色标记走过的格子)每个格子上都有水,水从高处流向低处,问那个格子的水可以流向太平洋和大西洋。原创 2025-01-06 16:33:36 · 402 阅读 · 0 评论 -
综合练习dfs_2(N皇后 解数独 单词搜索)
一共有9个格子,我们不要考虑一个格子一个格子进行考虑,第一个Q放在第一行的第一个格子,第二个Q放在第一行的第二个格子。row[9][10] 判断行 [9]9行 [10]该行内是否存在对应数 eg.row[0][1]=true 该行第一个行中有1。gird[3][3][10] 把9个格子分成三份 下标0 1 2 /3都对应0,[10]用来统计每个大格子中是否存在对应的数。,n=3就可以分为3中情况,再分别以这3种情况再进行划分,第二行中Q可以放在哪里。,n=3有几条正对角线,可看出5条(n*2-1)。原创 2025-01-05 16:32:11 · 949 阅读 · 0 评论 -
综合练习dfs_1
递归返回的路径字符数肯定是n*2的,我们直接递归枚举出所有的情况,再进行剪枝剪去不能组成括号的情况:1.左括号数不能大于n 2.在递归过程中右括号的数不能大于左括号的数。因为不能出现重复的eg.[1,2] [2,1],所以在递归时要进行剪枝 eg.2_ _ _选数时不能选自身 也不能选前面的数,只能选后面的数。eg.[1,1,1,2] 看似可以选4个数,但为了不重复第一个数只能选1_ _ _ 2_ _ _。当我们选了第一个1,第二个1第三个1就不能选了,因为以第2 3个1开头的数和第一个1都是值一样的。原创 2025-01-04 16:23:58 · 902 阅读 · 0 评论 -
穷举vs暴搜vs深搜vs回溯vs剪枝_全排列_子集(重点)
递归解决:一开始选一个数,递归进入下一层再选一个新的数,直到到最后一个数。定义一个全局的path数组记录一条路径的数,再定义一个全局的二维数组re记录每条路径。方法二就是根据选数的个数来找,选0个数的组合 1个数的组合 2个数的组合...当我们选完一个数后,选下一个数时,只能选该数在nums数组后面的数。传参数pos标记该数在nums数组中的位置,for循环遍历它后面的数。每一次进入dfs函数时,当前的path都是一次结果,存入直接返回。这样我们就画出了一个二叉树,遍历该二叉树,叶子节点就是结果。原创 2024-12-29 15:17:39 · 623 阅读 · 0 评论 -
二叉树的深搜_求根节点到叶节点数字之和_验证二叉搜索树_二叉树的所有路径
深度遍历二叉树时,用一个path字符串来记录经过的结点:不是叶子节点加val->,叶子节点加val,并返回。我们定义一个全局的变量prve记录上一个遍历数的大小,进行中序遍历,如果prve不是单调变化的,就说明它不是二叉搜索树。像上述左右子树+当前节点val==0,3个节点val都为0,根据上面的判断从叶子节点开始删也可以一个一个删除。每遍历一个节点就累加当前节点的val,如果为叶子节点就直接返回,有孩子继续递归累加数字。在遍历的过程中,维护一个当前路径列表,用来存储从根节点到当前节点的路径。原创 2024-12-28 20:11:36 · 558 阅读 · 0 评论 -
递归_汉诺塔_链表_快速求幂
逆序整个链表就可以分为逆转诺干个两个节点 可以用递归 dfs完成后面第一个节点后面所有节点的逆转,再把第一个 第二个节点逆转 并让第一个节点指向空就可以了。但-2^31 <= n <= 2^31-1 如果n==-2^31 它变为正数int会存存不下,所以n要用long long。如果n是偶数x^n=x^(n/2)*x^(n/2) 是奇数x^n=x^(n/2)*x^(n/2)*x。我们只需要处理好前两个节点的交换 剩下节点交换交给dfs并返回交换完成的头节点。一直找两链表头节点较小的节点 就可以用递归。原创 2024-12-27 17:37:50 · 301 阅读 · 0 评论 -
BFS 解决拓扑排序_ 课程表_火星词典
拓扑排序的基本要求有向无环图(DAG):拓扑排序只适用于没有环的有向图。如果图中有环,无法进行拓扑排序。唯一性:对于一个DAG,拓扑排序不一定是唯一的,可能有多种有效的拓扑排序结果。把操作看成结点,每个结点都有入度和出度,但每次都只能去入度=0的结点(没有指向它的),把该节点取下来 再看它指向的节点是否入度为0 为0就取下来。一直重复直到没有节点,或者没有入度为0的节点。排序的情况可能不止有一种 只要入度为0就可以取下来。原创 2024-12-25 21:27:14 · 769 阅读 · 0 评论 -
多源 BFS最短路问题_矩阵
我们要根据isWater数组推出最大的高度的数组,一开始我们只知道下标val值==1的海洋的高度是0,根据这个就可以推出海洋周围陆地的高度,因为高度差最大1且求最大高度的数组,海洋周围的陆地最大为1,再根据1再推2...先对四周进行bfs把为1的陆地标记或者直接设置为0,最后再遍历一次二维数组,把没有标记的1累计,返回累计的陆地面积。这道题和之前做的被淹没的陆地一样,只不过上到题是算还剩几块陆地,这个算剩余陆地的面积。之前我们都是做的一个点到另一个点的最短路径问题,现在有多个点,找它们到最短路的距离。原创 2024-12-18 16:30:00 · 335 阅读 · 0 评论 -
BFS 解决最短路问题_最短迷宫_基因变化_为高尔夫比赛砍树
用一个队列q存储当前层要遍历的节点,当前层节点全遍历完同时入队下一层要遍历的节点,并记录当前层数。遍历的时候用二维数组map记录遍历的位置,防止不必要的遍历。如下图砍的第一颗树必须是所有val值中最小的,也就是2,我们要求出来[0,0]起始下标到vla=2的下标的最短距离。vector<pair<int,int>>tree sort(tree.begin(),tree.end(),[](){里面实现根据val完成降序};和上一题基本一样,只是两层for循环不同,还有算的是单词的个数,不是变化的次数。原创 2024-12-17 13:30:00 · 567 阅读 · 0 评论 -
BFS 解决 FloodFill 算法_图像渲染_岛屿数量_被围绕的区域
bfs,广度优先遍历,先以一个点,向四周扩散,再以新扩散的点向四周扩散,直到没有目标点。起始点可以看作根节点,它四周的目标节点就相当于它的孩子,pop根节点 push它的孩子,遍历进入下一层,以此类推,直到队列为空。1.numIslands 函数通过遍历整个网格,每次遇到未访问的陆地 '1',就开始 BFS 搜索并将与之连接的所有陆地标记为已访问。完成后,靠近边界的O块及其连接的O块对应的map都为1。3.map 数组用于记录哪些点已经被访问过,避免重复访问。靠近边界的O块及其连接的O块,不能改。原创 2024-12-16 12:30:00 · 201 阅读 · 0 评论 -
优先级队列_ 前K个高频单词_数据流的中位数
如果定义成左边多,left==right left+1==right都可以看做平衡,反之left==right+1就不平衡了。3.比较器(比如 std::greater<int>小堆 或 std::less<int>大堆)。1.num<=left.top() || left.empty() 小于左边的最大值 或者 左边没有值 去左边。如果是偶数,左右两部均分。如果是奇数,肯定有一边多1,可以自己定义左边多,也可以定义成右边多。小根堆:堆顶是当前 k 个最大元素中的最小值,所以第 k 大的元素就是堆顶元素。原创 2024-12-15 12:30:00 · 953 阅读 · 0 评论 -
队列+宽搜_429. N 叉树的层序遍历_二叉树最大宽度
定义一个队列q,将一层的节点入队,并记录节点个数。根据节点的个数,出队列,并将其孩子入队列。出完队列,队列当前剩余节点的个数就是下次出队列的次数。2.知道队列头节点的下标 尾节点的下标 : i尾 - i头 +1 尾两节点的距离就是当前层最长的距离。1.存入队列中的元素类型为pair<TreeNode*,int>,也要把对应节点的下标传过去。入完后再把存有孩子节点的数组t复制到原数组q上,减少数组出队列移动元素的时间。3.算完当前层,再把它们左右孩子入队列,直到队列为空.出队父母节点,入队其孩子节点。原创 2024-12-14 19:45:18 · 199 阅读 · 0 评论 -
栈_删除字符串中的所有相邻重复项_基本计算器 II_字符串解码
借助栈结构,遍历字符串 放入一个字符前看看是否和栈顶元素相同,相同就出栈栈顶元素,如果为空或者不相等就入栈。遍历结束栈中剩余的字符就是目标结果。1.先用栈存储运算后的结果 char sym记录运算符(因为题目说所有数都是整数,所以sym初始化=+)一个表达式中* / 优先运算,我们先把* / 先运算完,最后再把这些数加起来。看当前sym是什么,我们可以用string来模拟栈,返回时就不用再从栈中获取返回结果。方法二:用两个栈,一个栈记录字符串 一个记录数字。+直接入栈 -取反入栈 *乘栈顶 /除栈顶。原创 2024-12-13 12:00:00 · 251 阅读 · 0 评论 -
字符串_最长公共前缀_最长回文子串_字符串相乘
tmp代表每一次运算出的结果 "837" "0516" "00294" 把它们加到ret,再reverse翻转,最后把末尾的0除去。奇数aba 取中间点i,left=i right=i left right分别向两边走,如果不相等就不是,直到全遍历完。倒着遍历a b,存在且为1 t++位数和 re+=t%2+'0'除去进位的余数 t/=2进位。1.定义一个数组 tmp[n+m] ,下标0存个位和个位无进制相乘的数,下标1存十位和个位,...(如果乘数有一方==0,那么re字符串就全为0)原创 2024-12-12 12:53:33 · 379 阅读 · 0 评论 -
哈希表_两数之和_字母异位词分组
a+b=target,遍历数组固定a,在数组中找b。eg.固定a=2,在数组中找7。有什么快速的方法能找到对应的数呢?先遍历一般数组,用哈希表记录所有的数及其下标,再遍历一次数组根据哈希表找对应的数的下标。但这会出现一个问题,如果有两个相同的值怎么办?哈希表中只能存唯一的一个Key。我们应该遍历一次数组,当我们遍历到一个数a时,应该在a数前面找b,没有就把a放入到哈希表中。然后继续下一个数,直到在该数前找到对应的b。两个字符串中每个字母出现的次数必须相同。原创 2024-12-11 17:26:36 · 275 阅读 · 0 评论 -
链表_逆序链表_合并链表
2.重复n次,逆序k长度的链表1.cur指向原链表中需要插入到新链表的结点2.prev进行头插时要用到的节点3.tmp记录下一次要插入位置的使用的结点(cur进入循环前的位置)(新链表的尾结点)从每条链表中取第一个元素(链表最小值),再从这些节点中选出一个最小的插入到新链表中。把s->next=nullptr断开链表后,新建head2新的空头节点,遍历右侧链表进行头插,完成逆序。我们可以再新建一个链表,进行尾插,第一次取左侧链表的结点,第二次取右侧链表节点,直到两个链表节点都取完。原创 2025-01-07 17:15:21 · 969 阅读 · 0 评论 -
分治_归并_归并排序(逆序对)
但cur2向右移,等再找到时,cur2左边的个数就包含的上一次找到的个数,就会重复。我们以降序为基础,cur1固定 cur2++找cur2<cur1,right-cur2+1(cur2右边)的数就是可以和cur1组成逆序对的数,再根据index映射到cur1在原数组的下标。想一想,如果第一次原数组,分为左右部分,左部分的个数=它的左部分+它的右部分+它的一左一右。再把临时数组排好的内容写回原数组。那逆序对的个数=左半部分逆序对的个数+右半部分逆序对的个数+左边取一个数和右边取一个数组成的逆序对的个数。原创 2024-12-08 18:19:23 · 965 阅读 · 0 评论 -
分治_快排_排序数组_第k个最值数_前K个最值数
先在数组中随机取一个数当作key,以key把数组分为三个部分,左边小于key的部分,中间等于key的部分,右边大于key的部分。要找次大的元素就把第一个元素和最后一个元素交换,并以刚交换的第一个元素为父母节点向下调整(传入的元素个数-1 ),再找出其中最大的元素。在快排中我们根据key,把数组分为>key ==key原创 2024-11-28 11:45:00 · 557 阅读 · 0 评论 -
模拟_6. N 字形变换_1419. 数青蛙
1.遍历给的混合字符串 如果是roak其中一个,就看前驱字符(o的前驱字符r r的前驱c)是否存在,存在前驱字符--,当前字符++。croakcroak 当遇到第二个c时,此时除了k为1 其它字符均为0,如果k不--,那么最后k存入的值就为2。3.看最后一个字符k前面的字符是否仍有存入的数,有就代表有不完整的croak,返回-1。>0表示已经有完整的croak,哈希表最后一个字符k--,当前字符c++我们用数组模拟哈希表,下标是字符在字符串的位置,记录出现的次数。2.如果是c,看哈希表k存入的数是否>0。原创 2024-11-20 20:20:10 · 266 阅读 · 0 评论 -
位运算_消失的两个数字
1~N中缺失了2个数,我们把这些数和1~N完整的数进行异或。得到的结果就是缺失的两个数a,b a^b的结果。这样两部分都可以异或出1个数来。原创 2024-11-20 18:30:49 · 301 阅读 · 0 评论 -
位运算_判定字符是否唯一
1.先用求和公式算出0~n所有数的和,再减去数组中数的和,剩下的就是缺失的数。0 1为1 0 0为0 1 1为0 和二进制满2进1一样。3.因为不需要统计出现的次数,只关心是否存在,并且原创 2024-11-11 21:48:49 · 332 阅读 · 0 评论 -
位运算_常见位运算总结
>:左移一位bit位原创 2024-11-11 18:04:38 · 275 阅读 · 0 评论 -
前缀和_560. 和为 K 的子数组
dp[i][j]=dp[i][j-1](左边面积)+dp[i-1][j](上面面积)-dp[i-][j-1](A多余的面积)+mat[i][j](右小块的面积)所以x1=max(0,i-k)+1 x2=min(m-1,i+k)+1 y1=max(0,j-k)+1 y2=min(n-1,j+k)+1。右下加面积=dp[x2][y2]-dp[x2][y1-1]-dp[x1-1][y2]+dp[x1-1][y1-1]但是我们dp[][]是从下标1开始填入有效值,mat数组从0开始,我们就需要+1建立映射关系。原创 2024-10-31 21:24:41 · 655 阅读 · 0 评论 -
前缀和_【模板】一维&&二维
我们求dp[i][j]就是求上述图像的面积A+B+C+D,现在我们知道D即arr[i][j]的值,还有已经算出的A+C dp[i][j-1] A+B dp[i-1][j] A dp[i-1][j-1]g[i]表示nums.size()-1~i+1元素的乘积,g[i-1]表示nums.size()-1~i+2元素的乘积,所以g[i]=g[i+1]*nums[i+1];整个图形面积为dp[x2][y2],A:dp[x1-1][y1-1] A+C:dp[x2][y1-1] A+B:dp[x1-1][y2]原创 2024-10-29 09:02:52 · 667 阅读 · 0 评论 -
二分查找_寻找旋转排序数组中的最小值&&LCR 173. 点名
nums[n-1]代表的就是第二段数组的最大值,如果nums[mid]>nums[n-1],说明整个数组的最小值不在mid的数组上,也就是在mid的右边->(left=mid+1)->求右端点值。如果在左区间的位置上那 目标下标肯定在该位置的右边left=mid+1,如果在右区间的位置因为可能是目标下标所以right=mid。这就可以用二分法求左端点,需要取靠左的值(mid=left+(right-left)/2)查找缺失的数,根据缺省数的位置可以把数组分为两部分,0 1 2 3 | 5。原创 2024-10-25 16:03:38 · 182 阅读 · 0 评论 -
二分查找_ x 的平方根&&搜索插入位置&&山脉数组的峰顶索引
把峰值看作递增的部分,如果nums[mid]>nums[mid-1]说明递增,那么mid可能是峰值,所以left不能=mid+1,left=mid,让right从右边找过来。递增数组,找到相等返回下标,反正按顺序插入(恰好比target大的值),也就是目标值>=target。下面有两种做法,不同点在于把峰值看做是递增数组上还是递减数组上,在递增数组就是求右端点,在递减数组就是求左端点。但无论那种情况,如果是递增那它的右边一定有峰值,如果递减它的左边一定有峰值。long long防止超出int范围。原创 2024-10-22 21:33:38 · 282 阅读 · 0 评论 -
二分查找_在排序数组中查找元素的第一个和最后一个位置
left指向8 right指向10,mid=left+(right-left) mid=0取靠左边的值 此时mid指向8,落在左区间,left=mid。,mid=left+(right-left) 还是向上取整 mid=left+(right-left+1)?mid=(left+right)/2 mid值不变,还是在右区间,right=mid right值也不变。mid=(left+right)/2 mid值不变,还是在左区间,left=mid left值也不变。此时left==right循环结束。原创 2024-10-22 19:28:03 · 1076 阅读 · 0 评论 -
滑动窗口_串联所有单词的子串&&最小覆盖子串
words里面的每个字符串长度是一样的,假设里面字符串长度为3,我们只需要进行3次遍历,就能找到所有的情况。第一次从s的第一个字母开始,第二次从第二个开始,...,等到第四次遍历从第四个字母开始,这种情况就和第一次遍历的情况一样了,会出现重复。首先哈希表h1里面存有words的所有字符串,哈希表h2记录进入窗口的字符串,如果长度大于words所有元素和,就出窗口。更新结果的时候,可以记录起始位置left-1 和长度right-(left-1)+1。此时窗口内的子字符串包含t字符串的所有字母,原创 2024-10-21 20:20:43 · 539 阅读 · 0 评论 -
滑动窗口_⽔果成篮&&找到字符串中所有字⺟异位词
思路二:我们没有必要每次都进行比较,我们可以用count记录h中有多少个有效字符,什么是有效字符?所以我们要保证h和h2中对应字母个数相同就可以,如果进入h的字符正好是缺少的字符count++,删除的字符如果不是多余的count--建立哈希表h2存入p字符串,哈希表h中存放与p字符串等长的s的子字符串,比较h和h2是否相同,从第一个开始直到最后。比如说h2中有3个a 1个b h为空,进入一个a,count++,进入一个b,count++,再进入一个b,此时h中b的个数>=h2的个数,count就不能++。原创 2024-10-11 21:14:49 · 319 阅读 · 0 评论 -
滑动窗口_⻓度最⼩的⼦数组&&⽆重复字符的最⻓⼦串&&将x减到0的最⼩操作数
思路一:两个指针,p1p2同时指向第一个元素。sum+=p2,如果sum原创 2025-01-07 17:55:01 · 342 阅读 · 0 评论 -
双指针_有效三角形个数&&三数之和&&四数之和
我们可以通过暴力枚举,三重for循环来算但,时间复杂度过高。注意:题目中不可以输出相同的三元组。思路一:三层for循环+set去重。思路二:排序+双指针+去重。有没有效率更高的算法呢?我们做过两数和为x的题,原创 2024-10-06 15:26:14 · 327 阅读 · 0 评论 -
双指针_快乐数&&盛最多水的容器
思路2:代码实现:盛最多水的容器原创 2024-06-04 18:44:08 · 470 阅读 · 0 评论 -
双指针_复写零
我们先让cur dest 都指向第一个元素前面,cur先++,根据cur是否为0来决定dest走一步还是两步。直到dest指向最后一个元素。原创 2024-05-31 17:31:13 · 885 阅读 · 0 评论