
LeetCode
Jelly_Believer
这个作者很懒,什么都没留下…
展开
-
leetcode 647回文子串 && 最长回文子串
dp数组:dp[i][j]表示区间i~j之间是否为回文串递推公式:当s[i] == s[j]时,若i == j,则此时肯定为回文子串,dp[i][j] = true;若j - i = 1,则此时也为回文子串,dp[i][j] = true;若j - i > 1,则需要判断i + 1 ~ j-1是否为回文串,即dp[i][j] = dp[i+1][j-1]是否为true;当s[i] != s[j],则 dp[i][j] =false;3.初始化, dp[i][j]初始化为false;...原创 2021-11-27 11:31:23 · 266 阅读 · 0 评论 -
编辑距离讲解。。
dp数组及其下标的含义dp[i][j]表示以i-1结尾的word1和以下标为j-1结尾的word2最近编辑距离确定递推公式if (word1[i - 1] == word2[j - 1]) ,则不用进行任何编辑操作,此时dp[i][j] = dp[i-1][j-1];if (word1[i - 1] != word2[j - 1]),则此时可以进行增删添操作。删除操作:此时删除word1[i-1],则dp[i][j] = dp[i-1][j] + 1(这个+1表示删除操作啦)替换操作: 此...原创 2021-11-26 10:20:11 · 120 阅读 · 0 评论 -
判断子序列 && 不同的子序列
双指针class Solution {public: bool isSubsequence(string s, string t) { int i = 0, j = 0; int res = 0; while(i < s.size() && j < t.size()){ if(s[i] == t[j]){ i++; res++..原创 2021-11-25 17:35:03 · 467 阅读 · 0 评论 -
最长重复子数组 && 最长公共子序列
dp[i][j]:以下标i-1结尾的A和下标j-1结尾的B,最长重复子数组长度为dp[i][j]递推公式:当A[i - 1] == B[j - 1],dp[i][j] = dp[i-1][j-1] + 1,故i和j得从1开始遍历。初始化由dp[i]数组的含义可知,dp[i][0]和dp[0][j]都是没有意义的,但dp[i][0] 和dp[0][j]要初始值,因为 为了方便递归公式dp[i][j] = dp[i - 1][j - 1] + 1;所以dp[i][0] 和dp[0][j]初始化为0...原创 2021-11-24 09:48:21 · 653 阅读 · 0 评论 -
最长上升子序列 && 最长连续递增子序列
dp[i]是可以由dp[j](j < i)推导而来的,故实验dynamic programmingdp[i]的定义:dp[i]表示i之前包括i的最长上升子序列的长度。状态转移方程位置i的最长升序子序列等于j从0到i-1各个位置的最长升序自序列 + 1的最大值故 if(nums[i] > nums[j]) dp[i] = max(dp[i], dp[j] + 1)这里不是要dp[i]与dp[j] + 1进行比较,而是要取dp[j] + 1的最大值dp[i]的初始化每一个i..原创 2021-11-24 08:52:45 · 528 阅读 · 0 评论 -
打家劫舍系列
dp[i]数组含义:考虑下标i(包括i)以内的房间,最多可以偷窃的金额为dp[i]注意!:dp[1] = max(nums[0], nums[1])而不是dp[1] = nums[1],因为dp[i]数组的定义是第i个房间能够偷窃到的最大金额class Solution {public: int rob(vector<int>& nums) { if(nums.size() == 1) return nums[0]; if(nums.s..原创 2021-11-23 09:03:08 · 118 阅读 · 0 评论 -
完全背包问题
有N件物品和一个最多能背重量为W的背包,第i件物品的重量为weight[i],价值为value[i]。每件物品都有无限多个(也就是可以放进背包多次),求解将哪些物品放入背包物品价值总和最大。完全背包和01背包问题唯一不同的地方就是,每种物品有无限件。使用一维数组时得先遍历物品再遍历背包,且背包得从大到小遍历,为了防止物品多次放入。而完全背包的物品是可以多次添加的,故要从小到大遍历。//先遍历物品再遍历背包for(int i = 0; i < weight.size(); i++){.原创 2021-11-20 15:21:25 · 803 阅读 · 0 评论 -
leetcode343 整数拆分 && 不同的二叉搜索树
一看题目就知道当前状态肯定是依赖于之前的状态的,故需要使用动态规划。动态规划五部曲:确定dp数组及其下标的含义dp[i]为第i个数字的最大乘积初始化dp数组数字0和1的拆分是没有意义的,故直接只初始化dp[2] = 1确定递推公式dp[i]可以由 j * (i - j) 以及j * dp[i-j]推导而来,这里i的取值为 3 <= i <= n, j的取值为 1<=j < i-1,可以保证i - j > 1,即 (i - j)最小取2故递推公式为dp[i..原创 2021-11-14 18:53:52 · 505 阅读 · 0 评论 -
leetcode738 单调递增的数字
局部最优:遇到s[i] < s[i-1],则令s[i-1]–,s[i] = ‘9’. 如32,就变成29;全局最优:得到小于等于N的最大单调递增的整数问题:遍历顺序,应该从后往前遍历,因为s[i-1]会–,从后往前遍历就总能保证s[i-1] >= s[i]了。记录从哪里开始开始统一变为9。比如1032的变化过程为 1032–> 1029 --> 0929–> 999(这里是从9开始往后全部变为9)...原创 2021-11-12 09:38:31 · 107 阅读 · 0 评论 -
leetcode56 合并区间
思路:按左边界排序,若相邻两个区间重叠(表现为intervals[i][0] <= end),则更新最大右边界end,这样就可以合并更多的区间了,整体最优:合并所有重叠的区间。class Solution {public: static bool cmp(const vector<int> &a, const vector<int> &b){ return a[0] < b[0]; } vector&l..原创 2021-11-09 19:28:08 · 3936 阅读 · 0 评论 -
leetcode 376摆动序列,最大子序列和,跳跃游戏
技巧:只需要统计摆动序列长度,故并不需要对原数组有什么修改若数组长度为二,则摆动长度为2。。则result初始为1(默认最右面有一个峰值),此时curDiff > 0 && preDiff <= 0,那么result++(计算了左面的峰值),最后得到的result就是2(峰值个数为2即摆动序列长度为2)class Solution {public: int wiggleMaxLength(vector<int>& nums) { .原创 2021-11-02 21:14:49 · 3262 阅读 · 0 评论 -
leetcode37 解数独(二维递归)
从左到右,一列一列的填,填完了就再填下一行class Solution {public: bool isValid(vector<vector<char>> &board, int row, int col, char k){ //检查列 for(int i = 0; i < 9; i++){ if(board[i][col] == k) return false; } .原创 2021-11-02 08:38:45 · 112 阅读 · 0 评论 -
Leetcode 重新安排行程
“一笔画”问题:通过图中所有边恰好一次且行遍所有顶点的通路称为欧拉通路通过图中所有边恰好一次且行遍所有顶点的回路称为欧拉回路具有欧拉回路的无向图称为欧拉图具有欧拉通路但不具有欧拉回路的无向图称为半欧拉图...原创 2021-10-29 10:42:34 · 167 阅读 · 0 评论 -
排列问题汇总
排列和组合的区别是 分顺序46全排列class Solution {public: vector<vector<int> > res; vector<int> path; void backtracking(vector<int> nums, vector<bool> &used){ if(path.size() == nums.size()){ res.push_bac原创 2021-10-27 17:15:55 · 186 阅读 · 0 评论 -
子集问题汇总
组合问题和分割问题都是收集树的叶子节点,而子集问题是找树的所有节点!(但子集也是组合问题,故普通子集也是很简单的)下面看子集问题的升级版:与子集的区别是 集合里面有重复元素,而且求取的子集得去重。去重方法和组合总和2的套路一样,分树枝去重和树层去重。更升级:通过排序,再加一个标记数组来达到去重的目的。而本题求自增子序列,是不能对原数组经行排序的,排完序的数组都是自增子序列了。所以不能使用之前的去重逻辑!在图中可以看出,同一父节点下的同层上使用过的元素就不能在使用了递归函数上面的u.原创 2021-10-27 15:31:16 · 311 阅读 · 0 评论 -
leetcode93 复原IP地址
思路:直接在原字符串s上面切割,即加’.’.因为规定了是固定切割数量3,即四段,故不能以startIndex = s.size()作为终止条件,设置一个变量pointNum, 当pointNum = 3得时候,就开始检查从startIndex到s.size()-1这一段是否valid,若有效则直接将s push进res中class Solution {public: // 判断字符串s在左闭又闭区间[start, end]所组成的数字是否合法 bool isValid(const..原创 2021-10-25 20:47:33 · 110 阅读 · 0 评论 -
131. 切割回文串
切割问题类似组合问题如对于字符串abcdef组合问题:选a之后,再到bcdef里选b,再到cdef里选c…切割问题:切割一个a之后,在bcdef中再去切割第二段,切割b之后在cdef中在切割第三段…如aab,先选a,再选a, 再选b 然后选aa 选b 最后选aab代码:class Solution {public: bool isHuiwen(string s){ int l = 0, r = s.size() - 1; if(s == "") r..原创 2021-10-25 09:44:13 · 138 阅读 · 0 评论 -
二叉搜索树的插入&& 删除&&修剪
class Solution {public: TreeNode* insertIntoBST(TreeNode* root, int val) { if(root == NULL){ TreeNode* node = new TreeNode(val); return node; } if(root->val > val) root->left = insertIntoBST(r.原创 2021-10-12 16:38:15 · 85 阅读 · 0 评论 -
二叉树的最近公共祖先&&二叉搜索树的最近公共祖先
自底向上寻找,即回溯,二叉树回溯的过程即是自底向上,而后序遍历就是天然的回溯过程。怎么判断一个结点是结点q和结点p的公共祖先呢:如果找到一个结点,其左子树出现结点q,右子树出现结点p,或者反之,则,该结点即位结点p和q的最近公共祖先确定返回值类型:class Solution {public: TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) { if(root ==...原创 2021-10-11 16:57:00 · 83 阅读 · 0 评论 -
二叉树的构造:从中序和后序序列构造二叉树(前序遍历)
一层层切割,故想到递归如果数组大小为0,说明是空结点了如果不为空,则去后序数组最后一个元素作为节点元素找到后序数组最后一个元素在中序数组的位置,作为切割点切割中序数组,切割为中序左数组和中序右数组(一定是先切割中序数组)切割后序数组,切为后序左数组和后序右数组递归处理左区间和右区间中序数组大小一定是和后序数组的大小相同的(这是必然)。故可以根据切好的中序来分割后序class Solution {public://inorder.size() == postorder.size.原创 2021-10-09 10:25:21 · 830 阅读 · 1 评论 -
二叉树左叶子之和(后序遍历)
通过一个flag来判断当前进入的是不是左结点class Solution {public: int res = 0; void traverse(TreeNode* root, int flag){ if(!root) return; if(flag && root->left == NULL && root->right == NULL){ res += root->.原创 2021-10-08 19:09:07 · 169 阅读 · 0 评论 -
二叉树的层次遍历系列
方法一:class Solution {public: vector<vector<int>> levelOrder(TreeNode* root) { if(!root) return {}; vector<vector<int> > res; queue<pair<TreeNode*, int> > q; int level = 0, lvl = 0; .原创 2021-10-05 10:12:50 · 102 阅读 · 0 评论 -
二叉树的迭代遍历
前序遍历前序是中左右,每次先处理根节点,然后分别把右和左孩子加入栈中(先右再左,这样出栈就是先左再右)代码(空节点不入栈)class Solution {public: vector<int> preorderTraversal(TreeNode* root) { stack<TreeNode*> st; vector<int> result; if (root == NULL) return resul原创 2021-10-04 10:17:10 · 77 阅读 · 0 评论 -
字符串(kmp)
在一个串中查找是否出现过另一个串,这是KMP的看家本领。next数组:遇到了有冲突的位置,就往前回退kmp的主要思想是当出现字符串不匹配时,可以知道一部分之前已经匹配的文本内容,可以利用这些信息避免从头再去做匹配了。next数组就是一个前缀表(prefix table)作用:是用来回退的,它记录了模式串与主串不匹配时,模式串应该从哪开始重新匹配。前缀表:记录下标i之前(包括i)的字符串中,有多大长度的相同前缀后缀最长相等前后缀前缀表(不减一)C++实现class Solution原创 2021-10-01 21:10:12 · 132 阅读 · 0 评论 -
数组问题汇总(1d + 2d)
坚持循环不变量的原则。 模拟顺时针画矩阵的过程。一圈下来,画四条边,画的每条边都要坚持一致的左闭右开或左开右闭,这样一圈才能安装统一的规则画下来。这里每一种颜色,代表一条边,我们遍历的长度,可以看出每一个拐角处的处理规则,拐角处让给新的一条边来继续画。代码:class Solution {public: vector<vector<int>> generateMatrix(int n) { vector<vector<int>..原创 2021-09-30 08:55:33 · 132 阅读 · 0 评论 -
leetcode加油站, 分发糖果,根据身高重建队列,用最少数量的箭引爆气球(贪心)
暴力解法for循环适合模拟从头到尾的遍历,而while循环适合模拟环形遍历,要善于使用whileclass Solution {public: int canCompleteCircuit(vector<int>& gas, vector<int>& cost) { int curSum = 0; int totalSum = 0; int start = 0; for (int i = .原创 2021-09-14 22:26:35 · 116 阅读 · 0 评论 -
栈问题合集
class Solution {public: string reverseParentheses(string s) { //u evol i ed et oc etco octe edocteel leetcode stack<string> st; string str; for(auto& ch : s){ if(ch == '('){ .原创 2021-09-02 16:14:27 · 189 阅读 · 0 评论 -
链表问题汇总
//快慢指针class Solution {public: ListNode* reverseList(ListNode* head) { if(head == NULL) return head; ListNode* pre = NULL, *cur = head, *tmp; while(cur != NULL){ tmp = cur->next; cur->.原创 2021-08-26 11:03:10 · 203 阅读 · 0 评论 -
字符串合集
双指针//时间复杂度 O(n)class Solution {public: string replaceSpace(string s) { int cnt = 0; int sOldSize = s.size(); for(int i = 0; i < s.size(); i++){ if(s[i] == ' ') cnt++; } s.resiz原创 2021-08-26 10:51:16 · 143 阅读 · 0 评论 -
Leetcode 207 邻接表(深度优先搜索)
class Solution {public: bool canFinish(int numCourses, vector<vector<int>>& prerequisites) { vector<vector<int> > adjacent(numCourses); vector<int> flags(numCourses); //用于判断节点是否.原创 2021-08-17 10:50:16 · 165 阅读 · 0 评论 -
Leetcode 554. 砖墙(哈希表 双指针)
class Solution {public: int leastBricks(vector<vector<int>>& wall) { int row = wall.size(); int res; unordered_map<int, int> mp; for(int i = 0, sum = 0; i < row; i++, sum = 0){ fo.原创 2021-08-07 09:29:53 · 158 阅读 · 0 评论 -
二叉搜索树问题:Leetcode1373. 二叉搜索子树的最大键值和(二叉搜索树 + 后序遍历)
class Solution {public: int maxSum = 0; int maxSumBST(TreeNode* root) { traverse(root); return maxSum; } vector<int> traverse(TreeNode* root){ //base case if(!root) return {1, INT_MAX, INT_MIN, 0};.原创 2021-08-05 18:41:15 · 102 阅读 · 0 评论 -
Leetcode 98. 验证二叉搜索树
思路:二叉搜索树在中序遍历下,结果是递增的。(二叉搜索树不能有重复元素,二叉搜索树可以为空)solution1:class Solution {public: vector<int> record; void traverse(TreeNode* root){ if(root == NULL) return; traverse(root->left); record.push_back(..原创 2021-08-03 19:44:08 · 98 阅读 · 0 评论 -
Leetcode 436. 寻找右区间
先对区间进行排序二分查找时传入右端点,查找大于等于右端点的第一个值题目要求返回索引,但是排序以后,索引的信息会丢失,又因为区间起点互不相同,故可以用哈希表来存储。class Solution {public: vector<int> findRightInterval(vector<vector<int>>& intervals) { int len = intervals.size(); if(len =...原创 2021-08-03 10:19:38 · 119 阅读 · 0 评论 -
剑指 Offer 11. 旋转数组的最小数字
思路:初始化 :初始化start和end分别指向nums数组的左右两端循环二分:令mid = (start + end) / 2(start <= mid < end),分以下三种情况:(1)当nums[mid] >nums[j]时,则选转点在左排序数组中,即在[mid + 1, j]中,此时令i = mid + 1;(2)当nums[mid] < nums[j]时,则旋转点在[i, mid]中,则令j = mid;(3)当nums[mid] = nums[j]时,无..原创 2021-08-02 19:58:15 · 74 阅读 · 0 评论 -
leetcode 81. 搜索旋转排序数组 II
class Solution {public: bool search(vector<int>& nums, int target) { if(nums.size() == 0) return false; int start = 0, end = nums.size() - 1; int mid; while(start <= end){ .原创 2021-08-02 08:59:58 · 72 阅读 · 0 评论 -
Leetcode74. 搜索二维矩阵(二分搜索)
考察知识点:(1)一维数组下标index到二维数组下标(x, y)的转换。row = index // n, col = index % n(2)二分查找class Solution {public: bool searchMatrix(vector<vector<int>>& matrix, int target) { if(matrix.size() == 0) return false; ..原创 2021-07-31 20:15:53 · 79 阅读 · 0 评论 -
2021-07-31 Disjkstra
分析:从k结点传输到所有结点的时间 = max(k到1结点所需最短时间,k到2结点所需最短时间…从k到n所需最短时间),因为传输是同时的,所以这道题就转换为图的最短路径问题先用Disjkstra算法求出各个点到k的最短距离,然后求出这些距离中的最大值int networkDelayTime(vector<vector<int>>& times, int n, int k){ queue<int> myQue; //此队列用于即将访问的结点 ..原创 2021-07-31 18:34:22 · 108 阅读 · 0 评论 -
Leetcode 最小高度树
拓扑排序法步骤:每次·删除所有当前入度为1的结点,直到最后剩下的节点数<=2原理:1.删除度为1的结点:相当于剪去所有当前的叶节点,最小高度树的层数必然下降一层(1)所以最小高度树的高度等于(删除次数+剩下结点数)(假设只有一个结点时高度为1)2.最后结点数 <= 2(1)最后剩下一个结点,则该节点为唯一解(2)最后剩下两个结点:以这两个结点为根的树都是最小高度树(3)最后剩下三个结点:那么必然有两个度为1的结点和一个度大于1的结点,可再次通过删除所有度为1的结点进而使得树的..原创 2021-07-31 17:26:20 · 162 阅读 · 0 评论 -
leetcode 二叉树的所有路径(回溯 + 递归)&&路径总和
递归函数参数与返回值结论:如果需要搜索整颗二叉树,则递归函数就不要返回值,如果要搜索其中一条符合条件的路径,递归函数就需要返回值,因为遇到符合条件的路径了就要及时返回。递归终止条件如果targetSum == 0, 同时到了叶子结点,说明找到了;否则若不为0到了叶子结点,说明没有找到。确定单层递归逻辑class Solution {public: bool hasPathSum(TreeNode* root, int targetSum) { if(...原创 2021-07-25 08:42:31 · 315 阅读 · 0 评论