
算法
算法
BeZer0
路漫漫其修远兮,吾将上下而求索
展开
-
ACM STL常见算法
1. lower_bound( ) 和 upper_bound( )头文件:#include<algorithm>lower_bound( begin,end,num,less<type>):从数组的begin位置到end-1位置二分查找第一个大于或等于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的...原创 2019-10-23 21:47:46 · 187 阅读 · 0 评论 -
C++ STL 常用容器
优先队列(priority_queue)头文件#include , 用于自定义数据的优先级, 让优先级高的排在队列前面,优先出队。优先队列具有队列的所有特性与基本操作,本质是一个堆实现的,操作如下:q.top() 访问队头元素q.empty() 队列是否为空q.size() 返回队列内元素个数q.push(xxx) 插入元素到队尾 (并排序)q.pop() 弹出队头元素swap(q...原创 2019-10-21 20:45:34 · 387 阅读 · 0 评论 -
ACM图论知识总结
1.欧拉图2.拓扑排序原创 2019-10-10 21:49:06 · 758 阅读 · 0 评论 -
309. Best Time to Buy and Sell Stock with Cooldown
考虑第一种情况,说明在第 i 天要么没进行操作,要么买了股票;考虑第二种情况,说明第 i 天卖出了股票;考虑第三种情况,说明第 i 天什么都没干。对应不同的情况进行操作即可。原创 2022-11-21 22:22:05 · 103 阅读 · 0 评论 -
240. Search a 2D Matrix II
假设目标元素为 14 ,首先我考虑了一种递归方式,即判断对角线元素的大小,从而排除两个正方形的区域(左上角区域元素均小于目标元素,右下角区域均大于目标元素),因此就可将问题缩小为图 1 中两个标红的区域,按此规则递归查找即可。当判断区域不是正方形时,先判断如图 2 所示蓝色区域,若未找到则再判断黄色的区域。每次从右上角元素开始向左搜索,如果遇到比目标元素小的元素,则将其下面的元素作为新的起点,直到找到目标元素或搜索结束,时间复杂度。原创 2022-11-16 19:19:52 · 229 阅读 · 0 评论 -
221. 最大正方形
首先考虑第一行或第一列的元素,发现边长只能为 0 或 1 ,再来考虑其他元素,可以发现边长只与左边元素、上边元素、左上方元素的边长有关,时间复杂度为。由于每个元素只用到上一行的 dp 值以及前一个元素的 dp 值,因此可以用一维数组和一个变量来记录 dp 表,从而使得空间复杂度降为。假设每一个元素为最大正方形的右下角点,那么可以对每个元素维护其对应最大正方形的边长。原创 2022-09-28 22:26:17 · 89 阅读 · 0 评论 -
207. 课程表
该题本质是求一个拓扑排序,若求不出,则说明存在环,由于不需要记录具体排序内容,因此可以省略栈,时间复杂度。,由于需要邻接表,因此空间复杂度。原创 2022-09-25 18:07:01 · 102 阅读 · 0 评论 -
215. 数组中的第 k 个最大元素
由于快速排序每次都能确定一个元素在数组中的位置,因此在排序过程中若枢轴为所求第 k 大值,则可终止排序。由于快速排序最慢的时间复杂度为。,为防止每次划分过程中取得最差结果,因此采用随机化来进行加速,时间复杂度。原创 2022-09-24 20:58:17 · 104 阅读 · 0 评论 -
200. 岛屿数量
遍历地图,每遇到一个连通图,都将其所有元素标记为true,然后遍历下一个连通图即可。可以遍历地图上所有1,如果周围有与其连接的1,则将其合并。原创 2022-07-28 21:57:47 · 100 阅读 · 0 评论 -
并 查 集
初始化最开始,每个元素各自为战,没有从属关系,因此将其所属(父结点)标为自己。查询用递归的方法来实现对代表元素的查询,逐层访问父结点,直至根结点。判断两个元素是否同属一个集合,只需判断二者根结点是否相同。合并先找到两个集合的根,然后将前者的父结点设为后者即可,反之亦然。...原创 2022-07-28 20:25:53 · 170 阅读 · 0 评论 -
198. 打家劫舍
取两者中的最大值即可,复杂度均为。原创 2022-07-27 18:58:07 · 117 阅读 · 0 评论 -
146. LRU 缓存
的存取操作,就需要使用双向链表进行头插与删除,使用哈希表对存取时已存在的结点进行锁定。原创 2022-07-25 21:39:48 · 202 阅读 · 0 评论 -
142. 环形链表 Ⅱ
用一个范围外的数字标记该结点被遍历过,若再次遇到该数则表示有环,且为第一个结点,时间复杂度。快指针每次走两步,慢指针每次走一步,若存在环,则它们必然在环内相遇。每次判断一下遍历的结点是否被遍历过即可,时间复杂度。表示两指针相遇位置再次到环入口位置的距离。表示环入口到两指针相遇位置的距离,由于所求点在起点出发的距离为。,因此在两指针相遇点加上。表示表头到环入口的距离,...原创 2022-07-18 21:53:45 · 101 阅读 · 0 评论 -
139. 单词拆分
其中check函数表示查找单词是否存在。数组来判断前i个字符组成的单词是否存在。组成的单词是否存在;的单词是否存在,前者存在即。原创 2022-07-14 22:04:44 · 100 阅读 · 0 评论 -
128. 最长连续序列
建立一个哈希表,然后统计每个元素作为起始点的长度即可。原创 2022-07-14 20:59:04 · 73 阅读 · 0 评论 -
98. 验证二叉搜索树
每次向下递归时限定一个最值,判断子树是否满足条件二叉搜索树的定义。时间复杂度 O(n)O(n)O(n) ,空间复杂度 O(n)O(n)O(n) :原创 2022-07-13 21:27:04 · 73 阅读 · 0 评论 -
79. 单词搜索
对每个位置进行搜索,看是否能找到目标单词即可,由于字母不可重复使用,因此需要用一个二维网格标记该单词是否被使用。时间复杂度 O(mn∗3l)O(mn*3^l)O(mn∗3l) ,空间复杂度 O(mn)O(mn)O(mn) ,m,nm,nm,n 为网格的长与宽,lll 为字符串的长度:...原创 2022-07-12 23:21:10 · 101 阅读 · 0 评论 -
75.颜色分类
统计三种颜色数量,重写数组,时间复杂度 O(n)O(n)O(n) ,空间复杂度 O(1)O(1)O(1) :单指针遍历两次,第一次将所有 0 交换到数组头部,第二遍将所有 1 交换到 0 后面的位置即可,时间复杂度 O(n)O(n)O(n) ,空间复杂度 O(1)O(1)O(1) :双指针使用双指针,分别代表 0 和 1 的位置,两个指针均指向数组头部,此时只遍历一次,因此需要协调好 0 和 1 的关系:直接交换表示将当前循环的元素与指针所指元素进行交换,判断交换分为两种情况:时间复杂度 O(n)O原创 2022-07-07 21:51:41 · 107 阅读 · 0 评论 -
57. 插入区间
首先考虑插入区间在被插入区间两边的情况,若不是上述两种情况,则对区间进行合并即可,时间复杂度 O(n)O(n)O(n) ,空间复杂度 O(1)O(1)O(1) :原创 2022-07-06 21:55:31 · 106 阅读 · 0 评论 -
56. 合并区间
按左端点排序,对同类区间合并即可,时间复杂度 O(nlogn)O(n\log n)O(nlogn) ,空间复杂度 O(logn)O(\log n)O(logn) :原创 2022-07-06 20:57:04 · 79 阅读 · 0 评论 -
55. 跳跃游戏
简单观察即可发现,如果在某个位置停下不能继续向前跳跃,则输出 false ,因此对每一个位置遍历到它最大跳跃位置并查看是否能继续前进即可。时间复杂度 O(n)O(n)O(n) ,空间复杂度 O(1)O(1)O(1) :...原创 2022-06-28 21:23:45 · 553 阅读 · 0 评论 -
34. 在排序数组中查找元素的第一个和最后一个位置
使用两次二分查找,一次查找 target 的开始位置,一次查找结束位置,时间复杂度 O(logn)O(\log n)O(logn) ,空间复杂度 O(1)O(1)O(1) :原创 2022-06-28 21:08:17 · 81 阅读 · 0 评论 -
102.二叉树的层序遍历
使用一个队列来存放每一层的结点,时间复杂度 O(n)O(n)O(n) ,空间复杂度 O(n)O(n)O(n) :原创 2022-06-28 20:30:34 · 143 阅读 · 0 评论 -
33.搜索旋转排序数组
题目描述基本上指定了二分搜索,那么二分搜索可用在两个递增序列中,因此只需要处理好边界条件即可。时间复杂度 O(logn)O(\log n)O(logn) ,空间复杂度 O(1)O(1)O(1) :原创 2022-06-27 22:07:26 · 76 阅读 · 0 评论 -
31.下一个排列
观察数组元素,可以发现下一个排列实际上就是将:时间复杂度 O(nlogn)O(n\log n)O(nlogn) ,空间复杂度 O(1)O(1)O(1) :贪心优化观察上一种解法,发现目标元素 i 其实是从末尾开始遍历的第一个非递增元素,j 是第一个大于 nums[i] 的元素,因此时间复杂度为 O(n)O(n)O(n) ,空间复杂度为 O(1)O(1)O(1) :...原创 2022-06-26 17:15:43 · 79 阅读 · 0 评论 -
19. 删除链表的倒数第 N 个结点
顾名思义,倒数第 n 个元素实际上就是让两个指针相隔 n 个元素进行遍历,快指针到达末尾元素则慢指针到达要删除结点的前一个元素,时间复杂度为 O(L)O(L)O(L) ,空间复杂度为 O(1)O(1)O(1) 。栈先把所有元素入栈,然后将 n 个元素出栈,此时栈顶为删除结点的前一个元素;若此时栈为空,则删除的结点是头结点,返回第二个结点即可。时间复杂度 O(L)O(L)O(L) ,空间复杂度 O(L)O(L)O(L) 。...原创 2022-06-22 21:33:51 · 155 阅读 · 0 评论 -
17.电话号码的字母组合
首先哈希记录一下每个数字对应的字母,然后遍历给定的数字串,每遍历一次就将该数字对应字母的所有排列加在上一个字母遍历后的串上即可。时间复杂度 O(3m×4n)O(3^m\times4^n)O(3m×4n) ,空间复杂度 O(3m+4n)O(3m+4n)O(3m+4n) ,m 、n 分别表示 3 个字母的数字个数和 4 个字母的数字个数。...原创 2022-06-21 21:10:20 · 89 阅读 · 0 评论 -
279. 完全平方数
维护一个数组,用于存储下标所对应的数的完全平方数最小个数,因此就可以将较大的数分解为较小数的和,也就可以转移状态。假设 f[0] = 0 ,并且每个 f 函数必然可以由一个比它小的 f 函数与一个选定的 n 构成,此时 f[n] = 1 + minn ,其中 1 表示选定的数 n ,它所代表的个数为 1 ;minn 表示当前最小的一组数的构成。在遍历前令 minn = INF ,那么对于 f[n = 1] ,从完全平方数的最小值 1 开始遍历,发现 1 * 1 没有超过 n = 1 ,那么 f[1] 的构成原创 2022-06-17 17:29:22 · 155 阅读 · 0 评论 -
322. 零钱兑换
题目记忆化搜索假设函数 F(amount)F(amount)F(amount) 表示凑出 amount 的最少硬币个数,那么此时扔掉一枚硬币,此时的情况即为:F(amount−coin)+1F(amount - coin) + 1F(amount−coin)+1 ,于是用动态规划的思想来处理问题,就得到了递推式:F(n)=F(n−1)+1F(0)=0F(负数)=−1F(n) = F(n - 1) + 1 \\ F(0) = 0 \\ F(负数) = -1F(n)=F(n−1)+1F(0)=0F(负数)原创 2022-04-20 21:03:14 · 271 阅读 · 0 评论 -
300. 最长上升子序列
题目动态规划对每一个数字求解当前最大严格递增子序列的长度即可:class Solution {public: int lengthOfLIS(vector<int>& nums) { vector<int> c; c.push_back(1); int ans = 1; for(int i = 1; i < nums.size(); ++i) { int tmp =原创 2022-04-18 20:22:27 · 167 阅读 · 0 评论 -
287. 寻找重复数
题目快慢指针法由于存在重复的数字,因此将数组看作链表索引后,必然存在环,那么环的入口数字即为重复数字。首先假设环长度为 L ,从起始位置到环的入口长度为 a ,环入口位置到快慢指针相遇位置的长度为 b ,从快慢指针相遇位置到下一次进入环(环入口)的长度为 c ,那么环的长度为:L=b+cL = b + cL=b+c 。假设快慢指针相遇时各自走了 slow=a+bslow=a+bslow=a+b ,fast=2(a+b)=a+b+kLfast=2(a+b)=a+b+kLfast=2(a+b)=a+b+原创 2022-04-15 18:36:23 · 1199 阅读 · 0 评论 -
647. 回文子串
题目中心扩展法顾名思义,寻找回文中心并不断向两边进行扩展即可,第一遍循环遍历回文串,第二个循环判断是否为回文,因此时间复杂度为 O(n2)O(n^2)O(n2) :class Solution {public: int countSubstrings(string s) { int res = s.size(); for(int i = 0; i < s.size(); ++i) { for(int p = i - 1, q =原创 2022-04-12 18:11:05 · 137 阅读 · 0 评论 -
148. 排序链表
题目插排法为每个元素选择在其前面元素所构成的序列中最合适的位置:class Solution {public: ListNode* sortList(ListNode* head) { if(!head) return nullptr; ListNode *p = head, *q = head->next; while(q) { // 4,3 if(q->val < head-原创 2022-03-17 19:58:21 · 642 阅读 · 0 评论 -
62. 不同路径
题目组合数学此题为组合数学的经典问题:格路问题,由题目可知,机器人可以向右走 n - 1 步,向下走 m - 1 步,因此由公式 f=C(m+n−2,m−1)f = C(m + n - 2, m - 1)f=C(m+n−2,m−1) ,编码实现即可:class Solution {public: int uniquePaths(int m, int n) { long long ans = 1; for (int i = n, j = 1; j < m;原创 2022-03-05 15:27:46 · 194 阅读 · 0 评论 -
15. 三数之和
题目排序 + 二重循环考虑到会出现数字重复的情况,因此首先应该对数据进行排序,这样就能保证重复数字出现在相邻的位置上,进而在运算过程中可以将其去除。由于排序后的数据满足从小到大的规律,因此前面两数之和的配对数字必然在后面,因此可以从前后两个方向进行查找。在查找过程中,如果若三数之和大于 0 ,表示第三个数字偏大,此时需要向前遍历更小的数字;反之若小于 0 ,则表示没有三数之和等于 0 的情况。因此将所有三数之和等于 0 的数字找出即可。在前两个数字遍历的过程中,若当前数字与前一个数字相同,则出现了原创 2022-02-28 13:02:36 · 81 阅读 · 0 评论 -
49. 字母异位词分组
题目排序要做分组,就需要构建一个哈希表,那么找到 key 值就是关键,考虑到相同组的单词所有字母排序后相同,因此可作为键值处理:class Solution {public: vector<vector<string>> groupAnagrams(vector<string>& strs) { unordered_map<string, vector<string>> mp; for(str原创 2021-12-22 17:28:48 · 563 阅读 · 1 评论 -
739. 每日温度
题目暴力暴力有两种:一种是每次遍历当前位置后续的元素,寻找更大值,由于数组长度最大为 1e5 ,因此会超时;第二种是建立一个元素索引,每次遍历当前元素温度 +1 到 100 度的元素,若能找到,则为目标,若找不到,说明结果为 0 。class Solution {public: vector<int> dailyTemperatures(vector<int>& temperatures) { int n = temperatures.原创 2021-12-20 21:04:11 · 177 阅读 · 0 评论 -
236. 二叉树的最近公共祖先
题目简单递归既然是搜索最近的公共祖先,那么在遍历该点的时候,一定满足:该子树中两个结点均能搜索到;该子树的子树中必有一个结点搜索不到。class Solution {public: bool dfs(TreeNode* root, TreeNode* flag) { // 边界判断 if(root == nullptr) return false; // 搜索结点 flag if(root ==原创 2021-12-10 20:54:32 · 282 阅读 · 0 评论 -
64. 最小路径和
题目动态规划由于题目要求只能向下或者向右走,因此一个确定位置的结果只能跟它上方或左方的位置有关,因此可以建立状态转移方程:class Solution {public: int minPathSum(vector<vector<int>>& grid) { int m = grid.size(), n = grid[0].size(); int ans[m][n]; ans[0][0] = grid[0][0];原创 2021-12-09 20:40:33 · 141 阅读 · 0 评论 -
96. 不同的二叉搜索树
题目递归 + 记忆化存储一看这种题目,不是搜索就是动态规划,用深搜试试,发现超时,考虑到数据集较小,那么存储一下每次 n 的结果即可:class Solution {public: int dfs(int n) { if(ans[n]) return ans[n]; if(n == 1 || n == 0) return 1; int res = 0; for(int i = 0;原创 2021-12-08 22:09:08 · 75 阅读 · 0 评论