LeetCode
LeetCode刷题
Flamingo灬
多巴胺的绑架没有救赎,有的只是上瘾的囚徒。
展开
-
贪心-无重叠区间
题目说要移除最小数量的区间是他们不重复,这时候可以想一下怎样拍可以是他们更加散开一点,也就是将右区间从小到大排序,也能够想象到将左区间从小到大排序,他们就更拥挤一些,就靠的更近一些。注意: 可以认为区间的终点总是大于它的起点。区间 [1,2] 和 [2,3] 的边界相互“接触”,但没有相互重叠。因为我们使用了贪心,尽量把右区间小的先挑出来,给后面预留更多空间。要想到直接求重复的是比较困难的,求不重复的会容易很多。给定一个区间的集合,找到需要移除区间的最小数量,使剩余区间互不重叠。原创 2022-09-20 16:22:36 · 110 阅读 · 0 评论 -
贪心-用最少数量的箭引爆气球
在坐标 x 处射出一支箭,若有一个气球的直径的开始和结束坐标为 xstart,xend, 且满足 xstart ≤ x ≤ xend,则该气球会被引爆。因为通过最小有边界能判定是否相连,例如i-1的有边界如果大于i的左边界,则i-1和i号气球相连,这时候再判断i+1号气球是否和前面两个是否相连,是不是要把i+1的左边界跟前面两个气球右边界小的比较,可以画画图理解。思路:大致思路就是一个一个遍历,判断是否挨着,如果没挨着,那么前面的气球要被射,如果挨着了那么持续判断直到重合数量最多再射。原创 2022-09-19 20:27:41 · 107 阅读 · 0 评论 -
贪心-根据身高重建队列
因为vector的底层是数组,其有两个重要的属性,一个是size,一个是capicity,类似于一个是数组的组长,一个是数组本来的储存空间,如果你要insert或者push_back一个元素,如果储存空间不够,会先拷贝一个数组,该数组的储存空间是原来的两倍,然后再把所有元素拷贝进来,这样就导致了使用动态数组(vector)的效率非常低。请你重新构造并返回输入数组 people 所表示的队列。因为方法二中使用的是list,list的底层使用链表实现的,比vector底层用数组实现的插入删除效率要高的多。原创 2022-09-18 16:23:39 · 160 阅读 · 0 评论 -
贪心-分发糖果
其实只用记住一点,就是if语句里面有两个值,一个是需要修改的(candyVec[i]),一个是被比较的,那么被比较的一定是要已经修改好的,也就是说不能在动的。如果第二次是从左往右遍历,那么if语句里面的ratingsp[i]和ratings[i+1],前者是需要被修改的,后者是被比较的,但是后者H还没有被确定,也就是说前者如果修改好了,然后就是后者和后后者进行比较,后者就可能被改变,这导致了结果会被影响,所以第二次遍历的顺序要从后往前。那么这样下来,老师至少需要准备多少颗糖果呢?原创 2022-09-17 21:10:38 · 102 阅读 · 0 评论 -
贪心-加油站
因为如果在你确定了能转一圈的情况下,也就是说加油的总量减去耗油的总量是大于0的。那么在这种情况下,如果[0, j]区间小于零,那么[j+1, end]一定大于零。更加抽象一点就是,a+b>0,如果a原创 2022-09-17 20:19:45 · 234 阅读 · 0 评论 -
贪心-K次取反后最大化的数组和
注意:后面的if语句的条件是k%2,因为如果是偶数,翻转最后一个数两次相当于没有翻转,所以可以不管,如果是奇数,则只需要翻转一次。所需要注意的是每次翻转的时候不要忘记对Max和temp进行初始化,还有记录所翻转的值。第二次贪心,如果数组中没有负数了,就将绝对值最小的整数翻转过来,产生局部最大值。第一次贪心:如果数组中有负数,则将绝对值大的负数先翻转过来,产生局部最大值。局部最优:每次遍历所有数组求出只翻转一个数所产生的最大值。先进行排序,将绝对值大的放前面,绝对值小的放后面。整体最优:K次翻转产生最大值。原创 2022-09-17 15:03:55 · 109 阅读 · 0 评论 -
回溯-解数独
算法思想:首先看到这题第一想法就是穷举,但是很明显普通的穷举是无法求出答案的,所以利用回溯的方法,其实这题和n皇后问题很像,但是n皇后是每行只能放一个,而数独要放多个,这时候就想到需要用双重for循环来找到节点,然后n叉树的每一层是对该节点赋值,从1-9选择,所以n叉树中n为9。原创 2022-09-13 19:50:03 · 122 阅读 · 0 评论 -
回溯-n皇后
算法思想:主干还是回溯的经典模板,n叉树的每一层也就是棋盘的一行,每次都是在这一行的某列进行选取,选取的时候判断是否有效,然后再一行一行的往下递归,直至整个棋盘都遍历并且判断完成。判断就只需要判断在不同列和不同45和135度即可,因为本来就是一行一行往下的,不可能同行。注意棋盘是从[0][0]开始的。原创 2022-09-13 16:35:59 · 151 阅读 · 0 评论 -
回溯-重新安排行程
【代码】回溯-重新安排行程。原创 2022-09-12 14:19:57 · 148 阅读 · 0 评论 -
回溯-全排列 II
【代码】回溯-全排列 II。原创 2022-09-11 13:43:49 · 139 阅读 · 0 评论 -
回溯-全排列
这题也是经典的排列问题,相比于组合问题和切割问题,排列问题就不再需要startIndex了,因为排列每次都是从头开始排列,则不再需要知道到底是从数组的那个地方开始了。然后就是需要定义一个used数组,判断所有元素中有哪些被用过,用过了的就不能在取了。首先得知道排列和组合的区别,排列是有顺序的,例如[1, 2]和[2, 1]是不同的,而对于组合,他们是相同的。回溯的经典题型-排列问题。原创 2022-09-10 14:39:50 · 149 阅读 · 0 评论 -
回溯-递增子序列
难点:首先这题所给的数组里面会出现相同的元素,这个时候我们第一时间想到去重,但是因为他是求递增子序列,用used数组那个方法的话会改变数组里的元素顺序,所以想到用set集合,set集合有个特点就是里面不会有相同的元素,且默认是以升序排列的。然后就是结果要求path里的元素大于1。还有剪枝的时候在判断递增前,要加上path.size()等于0的时候也允许加入到path,所以我们每次可以把n叉树的一层的索取的数放到这个set里面去,保证了树层去重(利用find函数)。原创 2022-09-10 14:20:19 · 225 阅读 · 0 评论 -
回溯-子集 II
类似于组合问题里面那个集合里面有重复元素那题一样,只需要进行去重即可,进行树层去重,即在n叉树中同一层不能有相同的,那么怎么判断呢,就是如果这个元素和前一个元素相同,并且,前一个元素used为0,即前面那个元素已经被取过了。原创 2022-09-09 15:25:16 · 98 阅读 · 0 评论 -
回溯-子集
相较于组合问题和切割问题,子集问题最大的区别在于最终结果取的是n叉树的所有节点,而组合问题和切割问题取的是叶子节点。每次直接先保存结果到结果集中,在通过if判断终止条件,再for循环横向遍历。其实写过组合问题和切割问题后,子集问题相较于简单。回溯的一个提醒-子集问题。原创 2022-09-08 10:58:20 · 145 阅读 · 0 评论 -
回溯-复原IP地址
难点:怎么判断终止,这里用到的是当打点的数量为3的时候说明已经分段完,然后再对最后一段进行判断是否合法即可。那么怎么想到这个呢,我先开始想法是定义一个字符串,当长度是s的长度加三,则代表终止,但是这样有一点会变麻烦,就是这样写你每次往新字符串里面加东西就比较麻烦,因为你不能每次加一小段字符串加上 ‘.’,所以这个方法是比较方便的。还有就是每次回溯的时候,是i + 2,不是i + 1,因为加上了那个点,也不是startIndex + 2,这个要注意,startIndex只是用来确定分割线的。原创 2022-09-07 19:09:20 · 190 阅读 · 2 评论 -
回溯-分割回文串
算法思想:其实和组合问题非常类似,组合问题的取数其实对应切割问题的切割,切割问题就是在某个地方切割,也就是答案中的i,切割下来的就是startIndex到i这一段,然后递归,再回溯。回溯的一个重要题型--切割问题。原创 2022-09-07 12:31:08 · 158 阅读 · 0 评论 -
回溯-数组总和II
重点:used数组很重要,确定了在for循环中,也就是树的横向遍历中可以保证可以知道这个元素是否用过,当然前提是对该数组进行了排序,如果这个元素和前一个元素数值相同,并且used[i - 1]是false,则代表前一个元素在同一树层被使用过,如果used[i - 1] 是true,则代表前一个元素在同一个数枝被使用过,而在这个题目中在同一个数枝使用相同元素是允许的,而同一树层不允许,同一树层,代表出现了相同的组合,同一数枝,代表一个组合出现相同元素。原创 2022-09-06 22:01:45 · 90 阅读 · 0 评论 -
回溯-组合总和
算法思想:因为可以出现相同的数字,但是不能出现相同的组合,所以可以定义一个index,来确保不会出现相同的组合。那如何保证可以出现相同的数字呢,就是每次递归的时候,也就是调用backTracking函数的时候index不变,for循环遍历的集合起始元素不变。取了一个数,它的子树中可以去这个数,和这个数后面的数,而不能用这个数前面的数。原创 2022-09-06 17:31:49 · 73 阅读 · 0 评论 -
回溯-电话号码的字母组合
算法思想:首先第一步,也是比较重要的就是,如何完成数字和字母的映射,这里采用的是利用利用一个字符串数组来完成,其实就是通过下标和字符串的对应,因为下标刚好就是数字,所以可以通过字符减去字符0刚好就完成了与数字的对应。然后就是常规的一个回溯过程。原创 2022-09-06 16:51:03 · 134 阅读 · 0 评论 -
回溯算法-组合
算法思想:首先得知道,组合和排序的区别,组合和无序的,排序是有序的。写回溯类型的题目,心中需要有一棵n叉树,这棵n叉树横向遍历是for循环,纵向遍历是递归,递归多少次是看自己需求并且是一个剪纸的过程。原创 2022-09-05 15:27:06 · 276 阅读 · 1 评论 -
把二叉搜索树转换为累加树
思路:就是以右中左的顺序进行遍历,然后定义一个sum进行累加赋值。原创 2022-07-12 18:17:03 · 67 阅读 · 0 评论 -
将有序数组转换为二叉搜索树
时间复杂度:O(N)思路:主要思路就是二分法,每次递归取数组的中间元素,(注意如果是偶数的时候是取左边还是右边),递归的单层逻辑就是把数组的中间元素当为根节点,然后一层一层的遍历下去。多写一个函数的原因就是使用left和right更好的控制边界。...原创 2022-07-11 22:40:53 · 107 阅读 · 0 评论 -
(二叉搜索树)修剪二叉搜索树
时间复杂度O(n)思路:递归法还是有一点绕,整体步骤就是先确定好根节点,根节点如果有问题会出现两种情况,一是小于low,此时我们应该从根节点的右儿子中继续寻找合适的根节点,以为一旦根节点小于low,其左子树一定都小于low,第二种情况是大于high,同理,我们应该从其右儿子中去寻找,找好根节点后,然后再去确定其左儿子和右儿子,确定的方法与BST的增添和删除有异曲同工之妙,只是不需要有if条件的限制,因为现在是有方向性的遍历整颗树,而不是有方向性的遍历某一条边。...原创 2022-07-11 22:18:21 · 101 阅读 · 0 评论 -
删除二叉搜索树中的节点
时间复杂度:O(h)h为树的高度思路:相较于BST的插入操作,删除更为复杂,有五种情况,但是大致框架都是一样,为有返回值的遍历边(用返回值构造树的某条边),所以时间复杂度为O(h)。五种情况如下:(1)没有删除的节点,则遍历到空节点直接返回。(2)找到删除的节点,其左右儿子为空,则直接删除该节点,返回为空。(3)找到删除的节点,其左空右不空,删除该节点,返回右节点(右节点代替了该节点)。(4)找到删除的节点,其左不空右空,删除该节点,返回左节点(同理)。(5)找到删除的节点,左右都不空,将左子树原创 2022-07-10 14:00:16 · 384 阅读 · 0 评论 -
二叉搜索树的插入操作
思路:因为是二叉搜索树,递归可以有方向。如何递归,首先确定递归的返回值,明显是树的根节点,然后确定递归的终止条件,很明显当遍历到空节点是终止递归,终止的同时,返回插入的节点值,最终确定单层的递归逻辑,因为底层返回的插入的值,上一层就要接住底层返回的值,所以用到left和right来接住底层的返回值,最终返回root即可。迭代法:.........原创 2022-07-08 14:24:05 · 254 阅读 · 0 评论 -
二叉搜索树的最近公共祖先
时间复杂度:O(n)思路:因为是二叉搜索树,所以它是有序的,所以不需要进行后序遍历,用回溯的思想,而是可以直接先序遍历,直到找到满足条件的那条边,即找到最近公共祖先,而公共祖先满足的条件就是cur的val在p的val和val之间即可,但是前提条件是从上到下开始遍历,所以用到先序遍历。......原创 2022-07-08 13:21:44 · 200 阅读 · 0 评论 -
二叉树的最近公共祖先
class Solution {public: TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) { if(root == p || root == q || root == NULL) return root; TreeNode* left = lowestCommonAncestor(root->left, p, q); //左 Tre.原创 2022-05-30 15:05:39 · 64 阅读 · 0 评论 -
二叉搜索树的众数
首先我们可以先试一下如果他是个普通的二叉树,我们该如何处理这题,我们很容易想到用到map映射,键是搜索树结点的值,值是出现的频率。先把树遍历一遍,把map映射先初始化,然后对map的值进行排序,然后就很容易找到众数,但是unordered_map容器内部是无序的,也没有相关的函数使用,所以把map里的元素通过pair放到vector数组里面去,然后自己定义cmp函数,比较pair元素的second,也就是频率,把这个函数参数放到sort函数里面去,然后取与vector第一个元素频率相同的前几个就行代码如.原创 2022-05-29 13:55:32 · 137 阅读 · 0 评论 -
验证搜索二叉树
知识点搜索二叉树除了他们结点之间有序外,还有一个很重要的特性,就是中序遍历搜索二叉树时,会发现是一个递增的序列。思路:我们可以利用这个特性对搜索二叉树进行中序遍历,遍历的同时将结果记录在一个数组中,然后对这个数组进行判断看起是否递增。class Solution {private: vector<int> vec; void traversal(TreeNode* root) { if (root == NULL) return; tra.原创 2022-05-28 10:59:44 · 104 阅读 · 0 评论 -
搜索二叉树
二叉搜索树的特性就是其结点之间的有序性,即根的值大于其左儿子的值,而且小于其右儿子的值。这样导致了我们递归或者迭代的时候需要改一下以前的方法,不然就浪费了其搜索二叉树的特性。方法一:迭代法class Solution {public: TreeNode* searchBST(TreeNode* root, int val) { while (root != NULL) { if (root->val > val) root = root-&.原创 2022-05-27 09:35:31 · 45 阅读 · 0 评论 -
合并二叉树
方法一:迭代法(层序遍历)class Solution {public: TreeNode* mergeTrees(TreeNode* r1, TreeNode* r2) { if (r1 == nullptr) return r2; if (r2 == nullptr) return r1; queue<TreeNode*> que; que.push(r1); que.push(r2); .原创 2022-05-26 17:07:22 · 77 阅读 · 0 评论 -
(二叉树)最大二叉树
class Solution {public: TreeNode* traversal(vector<int>& nums, int left, int right) { if (left - right >= 0) return NULL; TreeNode* root = new TreeNode(0); int maxIndex = left; for (int i = left + 1; i <.原创 2022-05-24 18:12:30 · 80 阅读 · 0 评论 -
平衡二叉树
LeetCode-110方法:递归class Solution {public: int getHeight(TreeNode* root) { if (root == nullptr) { return 0; } int leftHeight = getHeight(root->left); //左 if (leftHeight == -1) { return -1原创 2022-05-23 23:05:07 · 43 阅读 · 0 评论 -
知道中序和后序(或先序)构造二叉树
```cppclass Solution {public: TreeNode* traversal(vector<int>& inorder, vector<int>& postorder) { //后序为空返回空 if (postorder.size() == 0) return NULL; //可以去掉这句话 //取后序的末尾结点进行切割 int rootValue = posto..原创 2022-05-23 22:34:21 · 321 阅读 · 0 评论 -
完全二叉树节点个数
方法一:经典层序遍历,迭代法class Solution {public: int countNodes(TreeNode* root) { int sum = 0; queue<TreeNode*> que; if (root != nullptr) { que.push(root); } else { return 0; } ...原创 2022-05-17 19:04:16 · 86 阅读 · 0 评论 -
对称二叉树
class Solution {public: bool compare(TreeNode* left, TreeNode* right) { if (left == nullptr && right == nullptr) { return false; } else if (left != nullptr && right == nullptr) { return false;...原创 2022-05-16 19:25:18 · 997 阅读 · 1 评论 -
反转二叉树
方法一:递归法-先序遍历(后序遍历也可,注意中序遍历会出现同一颗树反转了两次的情况)class Solution {public: TreeNode* invertTree(TreeNode* root) { if (root == nullptr) { return root; } swap(root->left, root->right); invertTree(root->le..原创 2022-05-15 16:07:18 · 134 阅读 · 0 评论 -
二叉树的最小深度
方法一:递归法class Solution {public: int minDepth(TreeNode* root) { int height = 0; if (root == nullptr) { return height; } if (root->left == nullptr && root->right != nullptr) { retur原创 2022-05-15 15:33:54 · 226 阅读 · 0 评论 -
二叉树的最大深度
方法一:递归class Solution {public: int maxDepth(TreeNode* root) { int height = 0; if (root == NULL) { return height; } else { int height1 = maxDepth(root->left) + 1; int height2 = maxDepth..原创 2022-05-14 21:34:09 · 108 阅读 · 0 评论 -
手撕二叉树的层序遍历
class Solution {public: vector<vector<int>> levelOrder(TreeNode* root) { queue<TreeNode*> que; vector<vector<int>> res; if (root != nullptr) { que.push(root); } while...原创 2022-05-11 23:03:27 · 308 阅读 · 0 评论