02 2021 档案
摘要:题目 分析 自己想着dp,结果比赛一直卡住。今天看y总直播又学习到了。本题直接暴力搜索就可,用四进制搜。从40——4m减1,并且要排除掉每一位上3的可能。简而言之,就是将一个配料方案看成一个m位的四进制数 代码 1 class Solution { 2 public: 3 int closestCo
阅读全文
摘要:题目 LeetCode102.二叉树的层序遍历 代码 1 class Solution { 2 public: 3 4 vector<vector<int>>ans; 5 vector<vector<int>> levelOrder(TreeNode* root) { 6 if(root == NU
阅读全文
摘要:题目 给定一个n个点m条边的有向图,点的编号是1到n,图中可能存在重边和自环。 请输出任意一个该有向图的拓扑序列,如果拓扑序列不存在,则输出-1。 若一个由图中所有点构成的序列A满足:对于图中的每条边(x, y),x在A中都出现在y之前,则称A是该图的一个拓扑序列。 输入格式 第一行包含两个整数n和
阅读全文
摘要:题目 分析 所有边的长度都是1,权值相同,用BFS求最短路 代码 1 #include<iostream> 2 #include<cstring> 3 #include<algorithm> 4 #include<queue> 5 using namespace std; 6 7 const int
阅读全文
摘要:题目 分析 DFS,一次遍历,求出每个结点去除该点后的最大连通块的个数,同时更新ans(全局变量存放最终结果) 代码 1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 using namespace std; 5 6 c
阅读全文
摘要:题目 分析 代码 1 class Solution { 2 public: 3 void dfs(TreeNode* root,vector<int>&res){ 4 if(root == NULL) return; 5 6 dfs(root->left,res); 7 res.push_back(
阅读全文
摘要:题目 分析 后序遍历的非递归写法基本上就是按照前序遍历的非递归写出来的。前序遍历:根左右,后序遍历:左右根。如果把前序遍历的结果反转:得到根右左。这就启发我们,前序遍历的非递归代码基本不变,只需要将右孩子先入栈改为左孩子先入栈即可。这样得到的遍历顺序是:根右左。最后反转得到左右根 代码(递归) 1
阅读全文
摘要:题目 分析 用栈来模拟前序遍历,注意右孩子先进左孩子后进,这样出栈顺序就是先左后右! 代码(递归) /** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode
阅读全文
摘要:题目 分析 最短路,权值相同,用BFS 代码 1 #include<iostream> 2 #include<algorithm> 3 #include<queue> 4 #include<cstring> 5 using namespace std; 6 7 const int N = 110;
阅读全文
摘要:题目 分析一 本问题可以按照全排列的dfs来写。生成一个排列数,下标 i 对应第 i 行,其上的数字代表放哪一列。 代码 1 #include<iostream> 2 #include<algorithm> 3 using namespace std; 4 const int N = 20;//这里
阅读全文
摘要:题目 分析 代码 1 #include<iostream> 2 #include<algorithm> 3 using namespace std; 4 const int N = 7; 5 6 bool st[N]; 7 int path[N]; 8 9 void dfs(int n,int u)
阅读全文
摘要:题目 参考代码随想录 分析 本题可看出为完全背包问题。关键是dp[i]表示什么?dp[i] == true 表示长度为 i 的字符串可以词典中的单词完全划分。 确定递推公式 : if([j, i] 这个区间的子串出现在字典里 && dp[j]是true) 那么 dp[i] = true。 初始化:
阅读全文
摘要:题目 分析 本题的完全平方数可以重复取,为完全背包问题。dp[i] 表示 凑成 j 的完全平方数的最少个数。递推公式就是从背包问题推出来的 dp[j] = min(dp[j],dp[j-nums[i]] + 1) 初始化,因为求最小值,为了让初始值覆盖结果,所以将初始值设为正无穷。dp[0] = 0
阅读全文
摘要:题目 分析 根据最长公共子序列中状态表示的技巧,本题依旧两个串。状态标识设 dp[i,j] 表示将a[1-i] 变为 b[1-j] 的所有操作方式的集合中最少操作次数。 其实做了几道线性dp的题目,发现还是有些技巧:就是大都根据最后一个状态或者最后一个或一对元素考虑 递推公式的推导:考虑元素a[i]
阅读全文
摘要:题目 分析 状态表示,这里有个技巧,题目涉及两个字符串我们一般采用二维dp数组(经验)。 f(i,j)表示所有在第一个序列前 i 个字母中出现,且在第二个序列前 j 个字母出现的子序列的最长长度。重点是如何找递推公式。。。。 设第一个序列为a[]、第二个序列为b[]。f(i,j)所表示的最长子序列的
阅读全文
摘要:题目 分析 下图为y总的递推公式分析 dp[i] 表示 开头到 i 处最长上升子序列的长度。思考递推公式,如何由小的状态推大状态? 以第 i 个数结尾的上升子序列的构成:仅含 i 位置这一个数(意味着前面上升子序列)或者 若a[i - 1] < a[i] 时,dp[i - 1] + 1。由于dp[i
阅读全文
摘要:题目 分析 完全背包问题。dp[j]表示和为j的最小硬币个数。最大最小值问题递推公式 dp[j] = min(dp[j],dp[j-coins[i]] + 1) 代码 1 class Solution { 2 public: 3 int coinChange(vector<int>& coins,
阅读全文
摘要:做了LeetCode背包几道题吧,有些感觉了,故来总结一波。本文只针对01背包和完全背包,对于考研复试够用了。其他背包有待补充....... 参考代码随想录Carl和博文 如何区分01背包和完全背包? 每种物品只能取一次(或nums数组中的每个数字只能用一次)为01背包。每种物品有无数个(或nums
阅读全文
摘要:题目 分析 本题要结合LeetCode518.零钱兑换II这道题一起看,零钱兑换是组合个数总和,而本题排列个数总和,也就是说 (1, 2, 1) 和 (2, 1, 1)是不同的。遍历顺序:要先遍历背包容量再遍历物品。正好与组合问题遍历顺序相反,组合问题不允许重复,所以要先遍历物品再遍历背包容量。由于
阅读全文
摘要:题目 分析 此题组合问题,首先看能否回溯,数据范围太大,会超时。题目中说一种面额的硬币有无限个,本题为完全背包。本题与LeetCode 494目标和问题几乎一样。 dp[j]表示凑成总额 j 的种类。dp[0] = 1表示总额0不取任何硬币,这也是一种方法,所以为1,若初始值设为0,那么dp数组全为
阅读全文
摘要:题目 ACwing 分析 完全背包与01背包的区别在于,每种物品是否可以无限个。意思就是完全背包可以重复取同一间物品。代码上与01背包的不同点在于,在遍历背包容量时要正序遍历,因为倒叙遍历对应只使用取一次物品的情况。 代码 #include<iostream> #include<algorithm>
阅读全文
摘要:题目 分析 本题是两维01背包。每个子字符串为一件物品,并且只取一次,这就是01背包。两个维度体现在零的数量和一的数量上,也就是原始的01背包中的体积是一个维度,这里对应0的数量和1的数量。原始01背包中的价值对应每一个子字符串,选中子字符串就加1。dp【i】【j】表示最多i个零和最多j个1的最大集
阅读全文
摘要:题目 分析 这道题开始我是想用回溯,但一看数据量,肯定会超时(指数级的时间复杂度)。没有思路,想着应该是dp,怎么进行转化,转为我们熟悉的问题呢?题目的意思就是说将数组分成两堆n1,n2,使得 n1 - n2 = S 。且有n1 + n2 = sum。由这两个式子可得 n1 + n2 = 2 * n
阅读全文
摘要:题目 分析 本题和分割等和子集题目有异曲同工之妙。本题就是将石头尽可能分成重量相同的两堆,使得这两堆重量相减之后结果最小。这就转化为了分割相同等和子集的题目。 代码 二维dp数组 1 class Solution { 2 public: 3 int lastStoneWeightII(vector<
阅读全文
摘要:题目 分析 两个子集和相等,转化为找到所有元素总和一半的集合。注意不能回溯,因为时间复杂度为O(2N)会超时。可以将此问题看成0-1背包问题。背包容量为sum / 2。如果总和一半为奇数,那么不可分成两个相同总和的子集。在此问题种物品的重量和价值为数字本身的数值。设dp[i][j]为从0-i中选取不
阅读全文
摘要:题目 分析 首先要画个草图观察规律,n = 1 ,2, 3 时,结果分别为1,2,5。分析当 n = 3时,BST的种类构成:根节点为1,根节点为2,根节点为3。当根节点为1时,有两种形态 当根节点为2时,有一种形态 当根节点为3时,有两种形态 所以n为3时的BST数量为:根节点为1的BST个数 +
阅读全文
摘要:题目 分析 用dp[i]来表示 和为 i 的拆分正整数成绩最大值。拆分方式 :一、两个数 j ,i - j 。二、两个以上 j 、dp[i - j ],拆分(i - j ),j 的范围是从 1 到 i - 1 ,每次会得到dp[i] = max(j * (i - j) ,j * dp[j-i])。
阅读全文
摘要:题目 分析 dp[i][j] 表示从(0,0)到(i,j)有多少条路径。对dp数组初始化,每次移动只能向右或者向下,对第0行和第0列初始化。如果第0 行或者第0列某个位置上第一次出现了障碍物,那么之后的位置都无法走到。动态转移方程为:如果没有障碍物dp[i][j] = dp[i - 1][j] +
阅读全文
摘要:题目 分析 dp【i】【j】代表从(0,0)出发走到(i,j)位置上有多少种路径。关于dp数组的初始化,由于机器人每次只能向右或者向下移动一步。所以第 0 行和第 0 列dp数组初始化为 1。动态转移方程: dp[i][j] = dp[i - 1][j] + dp[i][j - 1],因为dp[i]
阅读全文
摘要:题目 分析 本题也是爬楼梯的扩展,题意不明确。参考LC评论区的解释后,豁然开朗。关键是对于cost代价值的理解,它代表的是从当前楼梯迈出所耗费的体力,而不是到达该层所需要的体力。可以翻译如下: 在首尾都加一个0分别代表地面,和楼顶 数组的每一个数字代表从当前楼梯迈出所需要耗费的体力 从地面开始,第一
阅读全文
摘要:题目 分析 用一维数组 dp[n] 表示爬到 n阶楼顶有多少种爬法,观察规律发现 dp[n] = dp[i-1] + dp[i-2],就是斐波那契数列。因为爬楼梯每次只能一个或两个台阶 代码 1 class Solution { 2 public: 3 int climbStairs(int n)
阅读全文
摘要:题目 代码 递归 1 class Solution { 2 public: 3 4 int fib(int n) { 5 if(n == 0) return 0; 6 if(n == 1) return 1; 7 return fib(n-1) + fib(n-2); 8 } 9 }; 时间复杂度O
阅读全文
摘要:题目 分析一 暴力枚举每个点,看看能不能成为回路,如无则返回-1。 代码 1 class Solution { 2 public: 3 int canCompleteCircuit(vector<int>& gas, vector<int>& cost) { 4 for(int i = 0;i <
阅读全文
摘要:问题: 刷LeetCode过程中,代码及报错如下: 1 class Solution { 2 public: 3 //按绝对值从大到小进行排列 4 bool cmp(int a,int b){ 5 return abs(a) > abs(b); 6 } 7 int largestSumAfterKN
阅读全文
摘要:题目 分析 每次取最小的反转即可,一次贪心 代码 1 class Solution { 2 public: 3 int largestSumAfterKNegations(vector<int>& A, int k) { 4 int sum = 0; 5 while(k){ 6 sort(A.beg
阅读全文
摘要:题目 分析 其实这题比较坑,不去关心每次究竟跳几步,而是看每次最多能跳到哪里,最后的最高跳范围包含结果就成功。贪心每一次最大范围。 需要注意的是,之前跳的范围不含本层,那么就为false。 代码 自己 1 class Solution { 2 public: 3 bool canJump(vecto
阅读全文
摘要:题目 分析 利润产生在低价买入,高价卖出中。所以递减序列是没有利润的。为了利润最大,我们要找局部最低点和局部最高点,注意是局部,而不是全局 如[7,1,5,3,6,4],选择1,5和3,6而不是直接从1到6。 所以贪心的局部最优就是 局部最小值和局部最大值的差值 这种思想有些像 LeetCode37
阅读全文
摘要:题目 分析 直接暴力,枚举每个起始点的最大和 代码 1 class Solution { 2 public: 3 int maxSubArray(vector<int>& nums) { 4 int res = INT_MIN; 5 for(int i = 0;i < nums.size();i++
阅读全文
摘要:题目 分析 摘自Carl大佬总结 局部最优:删除单调坡度上的节点(不包括单调坡度两端的节点),那么这个坡度就可以有两个局部峰值。实际操作上,其实连删除的操作都不用做,因为题目要求的是最长摆动子序列的长度,所以只需要统计数组的峰值数量就可以了(相当于是删除单一坡度上的节点,然后统计长度)但题目只要求返
阅读全文
摘要:题目 分析一 直接类似双指针比较,本质就是贪心,小饼干给小的胃口,贪心小胃口 代码一 1 class Solution { 2 public: 3 int findContentChildren(vector<int>& g, vector<int>& s) { 4 sort(g.begin(),g
阅读全文
摘要:题目 分析 本题区别于n皇后问题,n皇后问题是每一行放置一个,而解数独问题,是每行可放置多个数。实质就是二维递归,既对行进行递归,也对列进行递归。只要搜索到一种可以满足题意的结果立即返回,所以backtracking的类型是bool,意味可能不必搜索整个树。并且不需要判断结束条件,不会导致进入死循环
阅读全文
摘要:题目 分析 依旧回溯的模板题,要看出每次检查一个table,搜索树的元素是table 代码 1 class Solution { 2 public: 3 vector<vector<string>>res; 4 5 bool check(int row,int col,vector<string>t
阅读全文
摘要:题目 分析 https://mp.weixin.qq.com/s/3kmbS4qDsa6bkyxR92XCTA 代码 1 class Solution { 2 public: 3 unordered_map<string,map<string,int>>tar;//起点、<终点,次数> 4 bool
阅读全文
摘要:题目 给定一个可包含重复数字的序列 nums ,按任意顺序 返回所有不重复的全排列。 分析 本题是在 LeetCode46. 全排列 基础上的变形,就是加上序列中包含重复数字这一条件,导致的结果就是可能出现重复的序列。此题又回归到如何去重的问题? 1.排序 + used 数组 见 LeetCode4
阅读全文
摘要:题目 给定一个 没有重复 数字的序列,返回其所有可能的全排列。 思路 回溯解决排列问题。这里和组合问题、切割问题和子集问题最大的不同就是for循环里不用startIndex了。而used数组,其实就是记录此时path里都有哪些元素使用了,一个排列里一个元素只能使用一次 代码 1 class Solu
阅读全文
摘要:题目 给定一个整型数组, 你的任务是找到所有该数组的递增子序列,递增子序列的长度至少是2。 给定数组的长度不会超过15。 数组中的整数范围是 [-100,100]。 给定数组中可能包含重复数字,相等的数字应该被视为递增的一种情况。 法一分析 自己首先想法:本题和取子集的题目差不多,但不能通过排序+u
阅读全文
摘要:题目 给定一个可能包含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。说明:解集不能包含重复的子集。 分析 在LeetCode78.子集基础上的变形,解题思路来源 LeetCode40.组合总和II,这两个题目的核心就是,给定可能包含重复元素的集合,如何将结果去重?利用 used数组
阅读全文
摘要:题目 给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。 分析 代码 1 class Solution { 2 public: 3 vector<int>path; 4 vector<vector<in
阅读全文
摘要:题目 给定一个只包含数字的字符串,复原它并返回所有可能的 IP 地址格式。有效的 IP 地址 正好由四个整数(每个整数位于 0 到 255 之间组成,且不能含有前导 0),整数之间用 '.' 分隔。 例如:"0.1.2.201" 和 "192.168.1.1" 是 有效的 IP 地址,但是 "0.0
阅读全文