leetcode
文章平均质量分 50
alex_mist
coding....
展开
-
leetcode-计算器问题总结(栈)
一. 带乘除不带括号的计算器这题属于计算器问题中比较简单的,首先不带括号所以不用考虑括号匹配的问题,然后我们知道“先乘除后加减”,所以对于乘除应该直接求出结果,对于加减法来说应当记录每个数字前面的正负号然后直接将带符号的数入栈。还要注意的一点是,需要计算连续数字字符子串的十进制表达,这点好实现。最后栈中应当全部是带符号的数,对他们全部求和即可!例如:3-24,遇到数字4的时候,因为其前面的符号是,所以用栈顶的-2乘以4 = -8,所以栈内是3,-8,结果就是-5!class Solution {pu原创 2021-03-12 11:28:48 · 312 阅读 · 0 评论 -
leetcode-128. 最长连续序列
这题挺让我奇怪的,看起来没有hard的难度,但是正确的解法考察对各种STL时间复杂度的理解。题目要求时间复杂度做到O(n),那么其实是不能用map或set来做,因为它们的内部是由红黑树实现的(平衡搜索二叉树),其插入,查找的时间复杂度都在O(logN),将数组逐个插入维护map的操作时间复杂度就到了O(NlogN)了。正确的解法是,利用unordered_set的哈希特性,其插入查找的时间复杂度都在O(1),最坏是O(N)。对于数组中的每个数x,我们只需要查找在数组中是否存在x+1,x+2,x+3…x.原创 2021-02-12 15:38:51 · 136 阅读 · 0 评论 -
leetcode-703. 数据流中的第 K 大元素之TopK问题
今天是农历2021的最后一天,leetcode贴心的给了一道简单。这是一个经典的TopK问题,可以用排序时间复杂度在logN的算法解决。注意priority_queue是对堆排序的应用,但是需要决定对什么container维护堆排序:priority_queue<Type, Container, Functional>,Container必须是用数组实现的容器,比如vector,deque等等,但不能用 list。STL里面默认用的是vector!当我们采用升序的优先队列时需要手动指定conta原创 2021-02-11 14:40:27 · 277 阅读 · 0 评论 -
leetcode-992. K 个不同整数的子数组之滑动窗口
这个题目的示例其实是有误导性的,假如题目以:12,121,21,1212,212,12,23的方式给出,我们马上就可以发现其实就是求以A[i]结尾的且满足不同整数个数为K的子数组的个数!因此,我们其实只要知道使得左侧满足不同整数个数为k的最远的位置low,和使得左侧满足不同整数个数为k的最远的位置high,high-low就是我们要的结果!将每个位置的high-low求和,就是题解!这里如何维护high和low的位置有技巧,题目已经告诉了所以可以不用map,直接用长度为A.size()+1的vecto原创 2021-02-09 22:46:51 · 106 阅读 · 0 评论 -
leetcode-424. 替换后的最长重复字符之滑动窗口
据说这题是字节笔试的第一题,说不定leetcode这个月是双指针月?这题的思路我其实是有了,怎么样保证子串在k次替换以内成为全部重复呢?**只要子串长度减去子串中重复次数最多的元素出现的次数不大于k就可以!**但是怎么不断的维护统计重复次数最多的元素出现的次数是我没有想到的。实际上这题的解法,就是求以字符串中每个字符其最长重复长度,然后返回其中最长的作为答案!class Solution {public: int characterReplacement(string s, int k) {原创 2021-02-02 19:14:06 · 127 阅读 · 0 评论 -
leetcode-778. 水位上升的泳池中游泳之DFS+二分法与并查集
这道题的前一天的每日一题”1631. 最小体力消耗路径“也是相同的解法,只是在条件上有所不同,甚至这道hard比1631的medium还简单一些!对题目进行抽象,题目要求的从左上角到右下角其实可以抽象为寻找从左上角顶点到右下角的连通路径!很显然这个连通路径可以有多种,题目需要的是所经过的顶点的最大值最小的那条路径!所以采用图论的方法,将每个每个坐标方格抽象为图中的顶点,将相邻两点间数值大的那个点的值作为边权值,对所有边依旧边权值从小到大排序。对这些边进行并查集Union连接,直到发现连接完当前边后,左上原创 2021-01-30 14:30:29 · 195 阅读 · 0 评论 -
leetcode-947. 移除最多的同行或同列石头之DFS与并查集
题目这个月是图论月啊,各种并查集和图论算法。。。各个石头处于同列同行的性质其实就是石头之间的连接关系!要是删除了一个石头,那么由它所发出的边都要删除。而对于一个联通分量来说,是一定最多能删到只剩一个顶点的!因此这题其实就是要求是是有多少个联通分量!因此需要先根据stones列表来维护各个石头的联通关系,在同一列和同一行的石头都需要建立两两相连的边!然后通过DFS来求分量个数。class Solution {public: int removeStones(vector<vector&原创 2021-01-15 17:39:54 · 150 阅读 · 0 评论 -
leetcode-1203. 项目管理之拓扑排序
题目分析从题目可以比较简单的看出要使用拓扑排序,显然是需要对item建立图结构的,容易得到item的拓扑排序序列。但是题目要求:同一小组的项目,排序后在列表中彼此相邻!怎么理解这个条件呢?也就是说,属于同一个小组的项目必要可以独立的拎出来,不需要依赖别的小组的进度!假如小组A的部分依赖于小组B,而小组B也有部分依赖于小组A,那么其拓扑排序必定是:B --> A --> B,而无法做到题目要求的同一小组的项目,排序后在列表中彼此相邻。因此为了确定小组间的顺序,我们需要将各个小组要构建图结构,原创 2021-01-13 20:18:50 · 224 阅读 · 0 评论 -
leetcode-207.课程表之有向图的环路检测(拓扑排序,DFS)
从题目可以很容易看出是需要建立有向图并检测是否有回边,即是否存在环路的问题!这个需要确定前驱课程已经学过的例子其实就是拓扑排序最经典的例子。引用百度百科:通常,我们把这种顶点表示活动、边表示活动间先后关系的有向图称做顶点活动网(Activity On Vertex network),简称AOV网。例如,假定一个计算机专业的学生必须完成图3-4所列出的全部课程。在这里,课程代表活动,学习一门课程就表示进行一项活动,学习每门课程的先决条件是学完它的全部先修课程。如学习《数据结构》课程就必须安排在学完它.原创 2021-01-11 11:11:09 · 1070 阅读 · 0 评论 -
leetcode-399.除法求值之并查集
题目这道题要是不知道并查集的方法还可以通过DFS或BFS来做,这也是我第一次在leetcode遇到图相关的题目,很有意义!事实上题中的相除关系可以通过图的方式来表达,而queries中的求商可以通过求换算关系来得到,比如求a/d,那么我们要是能够将a和d都换算成相同的中间变量即可!我们可将a/b = 2.0变为两个顶点和一个边的关系来表示,a—>b,权重为2; 那么再加上b/c = 3.0,将图扩展为a—>b—>c,权重分别为2.0,3.0。那么当我们要求a/c的值的时候,只需要求a原创 2021-01-08 14:49:33 · 389 阅读 · 0 评论 -
解决回文串问题的两种模板解法
我们可以发现leetcode中有很多回文相关的问题,是常考点。这些题目大多是求回文子串长度或输出所有回文字串又或是分割回文串等,而大部分和回文串相关的问题都可以由两种模板方法解决。以最经典的leetcode第五题为例子:模板方法一:动态规划我们定义dp[i][j]表示字符串i~j是否是回文子串,那么我们可以得出状态转移方程if(dp[i+1][j-1] == 1 && s[i] == s[j]) dp[i][j] = 1完整代码:class Solution {publi原创 2020-12-22 21:13:17 · 200 阅读 · 2 评论 -
leetcode-二叉树的前中后遍历的迭代方法
题目就不用列了,递归法是很简单的,但是迭代法还是有一定难度,在此记录前序(easy):class Solution {public: vector<int> preorderTraversal(TreeNode* root) { vector<int> res; if(root == NULL) return res; stack<TreeNode*> s; s.push原创 2020-12-19 17:07:46 · 121 阅读 · 1 评论 -
leetcode-842. 将数组拆分成斐波那契序列之回溯法DFS
最近这几天的每日一题都不简单啊。。。这道题实在没想到真的是这么暴力的回溯,我还以为又是和前几天的每日一题有什么骚操作可以一次遍历搞定。。这里回溯的想法是尝试所有如下:1,2,3…; 1,23,4…; 1,234,5…; …12,3,4…; 12,34,5…; 12,345,6…; …其实就是去遍历分别以1,12,123,1234等为开头的情况,去找到分割数大于等于3且满足前两个的和为第三的条件!并且可以进行剪枝(来自官方题解):代码class Solution {public: .原创 2020-12-09 10:35:48 · 92 阅读 · 0 评论 -
leetcode-659. 分割数组为连续子序列
这题虽然是medium,虽然题目很好懂,虽然总觉得再想想就能解出来,但是这辈子都想不出来。。。官方题解还用了堆,优先队列,相当复杂,评论中一种方法很直白,可以总结为一句话:对于数x,要是有长度合法且末尾为x-1的组合,那么应当并入这个组合而不是另起炉灶class Solution {public: bool isPossible(vector<int>& nums) { unordered_map<int,int> nums_count; //原创 2020-12-08 11:11:46 · 99 阅读 · 0 评论 -
leetcode-42. 接雨水之单调栈
题目前天学习了一道单调栈的问题(拼接最大数),又找到一道类似方法的题目,而且也是hard难度的,说明这个单调栈是算法中比较难的点方法一想了很久u最后搞出一种时间复杂度为O(n2)的方法,是先找到数组中的最大值max,然后从1到max向上遍历,找出大于等于1,2,3…max的所有数,求他们的距离之和就是每一层可以装下的雨水!class Solution {public: int trap(vector<int>& height) { if(height.s原创 2020-12-04 13:54:12 · 157 阅读 · 0 评论 -
leetcode-321. 拼接最大数之单调栈
题目作为一道hard题目的意思还是比较好理解的,而且可以推知需要使用单调栈; 题目提到要求取出的数字保持在原数组中的相对顺序,而且要求拼接的数最大,那么可以分解为分别求两个数组能获得的保持原相对顺序且应当是降序的序列!其实就是求两个数组的各自的单调栈(单调递减),但是要注意的是题目还有长度限制,这里是题目的难点!转题解中的一个图,要是能drop掉的数等于0了,那么后续的数应当直接填补上:这里的drop_num等于数组长度减去要求的长度,表示的是按照递减条件能从单调栈pop出来的数的数量;求单调栈的方法原创 2020-12-04 13:24:51 · 134 阅读 · 0 评论 -
leetcode-222. 完全二叉树的节点个数
题目方法一年轻人不将武德,直接DFS遍历求解,但是没有用到题目完全二叉树的性质!!class Solution {public: int count = 0; int depth_max = 0; int countNodes(TreeNode* root) { DFS(root); return count; } void DFS(TreeNode* root){ if(root == NULL){原创 2020-11-24 22:09:13 · 92 阅读 · 0 评论 -
leetcode-48. 旋转图像
题目方法一其实在做这题的时候画图已经把这种方法给画出来了,但是没深入想,没有找到具体的规律!整体矩阵的顺时针旋转可以分解为:(1)每个外圈的旋转(2)每个圈都分为左上,左下,右上,右下(3)左上 = 左下; 左下 = 右下; 右下 = 右上; 右上 = 左上class Solution {public: void rotate(vector<vector<int>>& matrix) { int up_limit = 0;原创 2020-11-20 09:56:25 · 84 阅读 · 0 评论 -
leetcode-134. 加油站
题目这题我一开始没有注意,把cost[i]当作是从上一个加油站开到这一个加油站需要的油耗了,实际题目写的很清楚,是从当前油站开到下一油站的油耗; 因此,只要gas-cost的累加结果一直大于0,那就肯定可以跑一圈!但是怎么确定要从哪里跑呢,题解中提供了一个很好的思路:来自:https://leetcode-cn.com/problems/gas-station/solution/shi-yong-tu-de-si-xiang-fen-xi-gai-wen-ti-by-cyayc/只要我们找到累加的原创 2020-11-19 09:42:08 · 97 阅读 · 0 评论 -
leetcode-406. 根据身高重建队列
题目分析h代表的是人的身高,k代表的是前面比身高大于等于他的人的人数; 因此,为了知道一个一人前面有多少身高大于等于他的人,应当依据h进行降序排列; 并且我们知道,对于同等身高的人来说,k应当是升序的; 所以,自定义排序方法:对h降序排列,对k升序排列,并定义结果数组res,然后遍历这个排好序的数组,对于其k要大于等于当前res长度的(这个长度代表实际身高大于等于这个人的人数),直接插入末尾,而对于其k要小于当前res长度的需要插入到其k所指定的位置代码bool cmp(const vector&原创 2020-11-16 22:00:09 · 121 阅读 · 0 评论 -
leetcode-57.插入区间
题目leetcode的每日一题,看到是hard有些慌,但是看题目似乎并不难; 有两种想法,在本地空间对intervals进行修改,或新建vector来插入本地修改的方法需要做很多判断,而且需要在本地vector进行多次erase操作,效率并不会比新建vector效率高!本地修改代码(要是遇到很多需要合并的单元会导致很多erase操作,很耗时!):class Solution {public: vector<vector<int>> insert(vector<原创 2020-11-05 10:06:02 · 131 阅读 · 0 评论 -
腾讯2017暑期实习生编程题--删除最少的元素,获得最长回文串
题目典型的动态规划,和leetcode第6题最长回文字串很类似,难点在于写出构造方程(废话。。),在于当左右指针不等的时候如何推出结果!#include<string>#include<iostream>#include<vector>using namespace std;int Solution(string s){ int length = s.size(); vector<vector<int>> dp(len原创 2020-10-22 14:04:07 · 218 阅读 · 1 评论 -
leetcode-删除排序数组中的重复项+移除元素
删除排序数组中的重复项方法一暴力法,直接通过erase删除每一个重复的元素:class Solution {public: int removeDuplicates(vector<int>& nums) { vector<int>::iterator iter; for(iter = nums.begin();iter!=nums.end();){ if(iter!=nums.begin() &原创 2020-10-10 10:15:43 · 140 阅读 · 0 评论 -
leetcode-两两交换链表中的节点之DFS+迭代
class Solution {public: ListNode* swapPairs(ListNode* head) { ListNode* res = new ListNode; ListNode* tmp = res; res->next = head; while(head!=NULL && head->next!=NULL){ ListNode* first = head;原创 2020-10-08 19:50:29 · 117 阅读 · 0 评论 -
leetcode-合并K个升序链表之分治法+优先队列
题目对于K个链表的情况,不先求两个升序链表分治的情况!这正好是leetcode的一个简单题:合并两个有序链表合并两个有序链表解法一:新建一个链表,每次插入l1和l2中value小的那一个:class Solution {public: ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) { ListNode* res = new ListNode; res->next = NULL;原创 2020-09-29 10:09:14 · 205 阅读 · 0 评论 -
leetcode-三数之和,四数之和,n数之和的共性方法
最近leetcode也刷了100道了,开始二刷这100道题,并做每道做过题的相似题目;leetcode的第一题是两数之和,还有三数之和,四数之和… 其实他们都可以用相同的方法来解决,甚至可以一直推到n数之和!三数之和假如求两数之和,我们可以先将数组从大到小排序,然后用双指针的方法从两头往内收缩寻找: int i = 0; int j = nums.size() - 1; while(i<j) {原创 2020-09-02 15:43:47 · 354 阅读 · 0 评论 -
全排列和组合的DFS总结
全排列和组合的DFS的框架很相似,但是在每个位置上选择的方案有所不同。DFS的模板:if(...){ ... return;}//退出条件for(...){ ... DFS() ...}//for是选择列表全排列和组合的区别就在于选择列表上!组合在上一个位置选择过后,不能再往回看,只能将选择列表限制在除了前面遍历过之外的; 而全排列则可以继续从头选起,只要该选择没有选过!组合class Solution {public: vector<vector<原创 2020-08-27 16:19:17 · 436 阅读 · 0 评论 -
leecode-剪绳子(DP)和树的子结构
剪绳子这题读题就知道的用动态规划,因为很显然可以被分解为前面的结果,但是比较特别的是2,3这两个,因为2本身要被切的话,结果是1×1=1,3要被切的话是1×2=2; 它们两个被切的值是小于直接拿本身作为绳子的一段的,因此要从n=4的长度区分:dp[4] = max(dp[1]×d[3], dp[2]×dp[2]) = (1×3, 2×2) = 4dp[5] = max(dp[2]×dp[3]) = (2×3) = 6dp[6] = max(dp[2]×dp[4], dp[3]×dp[3]) = (2原创 2020-08-26 09:37:47 · 186 阅读 · 0 评论 -
leetcode-重复的子字符串
题目每日一题中的easy题,但是其实还蛮有意思的;我的方法很蠢,首先我们知道字符串的长度一定是子串的倍数,那么就去每种长度的子串都去尝试,将某一长度的字串*(字符串长度/字串长度)和原字符串进行比较,若相同说明这个字符串是可以由重复字串组合成的!class Solution {public: bool repeatedSubstringPattern(string s) { bool res = false; string str = ""原创 2020-08-24 15:02:30 · 233 阅读 · 0 评论 -
leetcode-分割等和子之0-1背包问题
0-1背包问题背包问题是经典的dp问题,可以分为0-1背包和完全背包,这里我们讨论0-1背包问题;问题场景一般是:背包最大容量为V,物品数量为N;体积数组:v[0…N-1] = {…}价值数组:c[0…N-1] = {…}求解能装下的最大价值,每个物品要么拿要么不能,只能拿一次;我们定义dp二维数组:dp[i][j]表示面对前i个物品,背包容积为j时,能获得的最大价值那么状态转移方程:dp[i][j] = max(dp[i-1][j],dp[i-1][j-v[i]]+c[i])那么主要原创 2020-08-19 16:41:26 · 172 阅读 · 0 评论 -
leetcode-有序链表转换二叉搜索树
题目二叉搜索树:若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树; 那么又如何满足高度平衡呢?每次都以中位数作为结点即可!方法一偷懒的方法,将链表遍历一遍,得到数组; 在数组中用二分法来找中位数:class Solution {public: TreeNode* sortedListToBST(ListNode* head) { vector<int>原创 2020-08-18 17:48:11 · 119 阅读 · 0 评论 -
leetcode-DFS两道easy:平衡二叉树+图像渲染
平衡二叉树考研的时候我记得这个平衡二叉树的题做过,用的方法是DFS; 自底向上后序遍历去计算每个结点的高度,指向NULL的空结点高度默认为0,定义一个flag标志位默认为true,若出现了左右子树的高度差的绝对值超过了1,那么置flag为false,代码:/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right;原创 2020-08-17 14:53:29 · 133 阅读 · 0 评论 -
leetcode-单词拆分之动态规划和DFS
题目方法一:DFS我采用的DFS极其愚蠢,把全排列的思想套到了这题上,用DFS穷举出wordDict中所有的排列那去和s做比较,效率及其低,不出意料的超时;class Solution {public: bool flag = false; bool wordBreak(string s, vector<string>& wordDict) { string tmp; DFS(s,wordDict,tmp); ret原创 2020-08-06 15:45:32 · 164 阅读 · 0 评论 -
leetcode-乘积最大子序和之动态规划
分析一开始的想法其实没有错,先计算整个数组中负数的个数,看是奇数个还是偶数个;若是偶数个,很简单,挨个乘就是了;但若是奇数,就需要去检查当前是第几个负数等,代码写起来非常之麻烦;其实这题和最大子序和有些类似,但是因为是乘法导致负数的影响很大; 多个正数的乘积的结果,也就是最大乘积遇到负数后,应当变成了最小乘积,再次遇到负数的时候,就再次变为最大; 我们需要同时维护:乘积最大子序和,乘积最小子序和;而且动态规划的特点是“无后效性”:无后效性是指如果在某个阶段上过程的状态已知,则从此阶段以后过程的.原创 2020-07-27 17:30:41 · 205 阅读 · 0 评论 -
leetcode-比特位计数之位运算与动态规划
分析从最直接的方法来看,可以分为两步,首先是要直接求出数n的位1个数;方法很巧妙:“如果一个整数不为0,那么这个整数至少有一位是1。如果我们把这个整数减1,那么原来处在整数最右边的1就会变为0,原来在1后面的所有的0都会变成1(如果最右边的1后面还有0的话)。其余所有位将不会受到影响。举个例子:一个二进制数1100,从右边数起第三位是处于最右边的一个1。减去1后,第三位变成0,它后面的两位0变成了1,而前面的1保持不变,因此得到的结果是1011.我们发现减1的结果是把最右边的一个1开始的所有位都取.原创 2020-07-22 10:46:58 · 208 阅读 · 0 评论 -
leetcode-三角形最小路径和之动态规划
分析一开始的想法非常愚蠢,定义dp[n][2],dp[i][0]来代表自顶向下到第n行的最小路径和,dp[i][1]代表最小路径和到的下标位置i; 实在是太蠢了,定义了这么个麻烦的dp数组,因此代码也相当的丑陋。。。实际上自底向上去推是非常简单的,定义dp[i][j]为到坐标为(i,j)的位置上时的最小路径和;自底向上,到每个元素位置的最小值可以由下一层来推出,推到dp[0][0]就是答案代码class Solution {public: int minimumTotal(vector.原创 2020-07-21 09:34:54 · 127 阅读 · 0 评论 -
leetcode-不同路径之动态规划
分析一开始没往动态规划上想,因为这用纯数学的方法是可以做的;因为m×n的棋盘,一定是需要m-1次向右和n-1次向下才可以到达最右下角的,因此我们把m-1次向右当作m-1个A元素,而n-1次向下当作n-1个B元素,而m-1个A元素有m个空,只需将n-1个B元素插入m个空即可;但是还要注意,这里不是一个萝卜一个坑,可以多个萝卜插一个坑,也就是可以多个B一起放在一个空中;动态规划还是很好分析的,定义dp数组:dp[i][j]代表从(0,0)到(i,j)位置的路径种类数量,因为一次只能向下或向右走,得到.原创 2020-07-05 15:06:49 · 178 阅读 · 0 评论 -
leetcode-最长上升子序列之动态规划
分析我一开始的想法是,定义一个二维dp数组,dp[len][2];其中dp[i][0]代表从最开始到i位置上的最长上升子序列的长度,但不一定包含位置i;dp[i][1]代表最开始到i位置上的最长上升子序列中,末尾的那个元素的大小;但是这种方法很蠢,它没有办法解决:10,9,2,5,3,4这种问题,因为它没有办法判断出2,5和2,3,4;正常题解也是动态规划,依旧是需要知道子序列的末尾元素,才能去判断大小;因此定义dp[i]为以nums[i]结尾的最长子序列的长度,那么只要找到位置i之前的所有元.原创 2020-06-30 15:25:01 · 173 阅读 · 0 评论 -
leetcode-有序矩阵中第K小的元素
class Solution {public: int kthSmallest(vector<vector<int>>& matrix, int k) { vector<int> tmp; int len = matrix.size(); cout<< len; for(int i=0;i<len;i++) { for(int j=0原创 2020-06-10 20:35:27 · 251 阅读 · 0 评论 -
leetcode-和为K的子数组之hash表(前缀和)
class Solution {public: int subarraySum(vector<int>& nums, int k) { map<int,int> m; for(int i=0;i<nums.size();i++) { int sum = 0; for(int j=0;j<=i;j++) {原创 2020-05-15 21:09:04 · 190 阅读 · 0 评论