刷题笔记
花无凋零之时
这个作者很懒,什么都没留下…
展开
-
二叉树中求最大路径和
又因为计算以根节点的树的最大路径和计算其左子树、右子树中的最大路径和函数功能相同,所以设计为递归算法。(单边最大值为root到达其某个子孙节点的最大值,或者root节点自身,即。定义递归函数DFS(root),返回值为经过root节点的。的最大值需要用一个变量 maxpath 来统计。题目来自LeetCode中,链接为。原创 2022-09-24 21:20:13 · 946 阅读 · 0 评论 -
【POJ】2253 Frogger
求最短路径中单次跳跃的最大值,可以使用Floyd算法求解:#include <iostream>#include <cstdio>#include <cstring>#include <cmath>using namespace std;const int N = 200 + 10;const int INF = 0x3f3f3f3f;double graph[N][N];double x[N], y[N];void Floyd(.原创 2022-03-15 11:05:20 · 181 阅读 · 0 评论 -
【POJ】1125 Stockbroker Grapevine
题目大意是要找出从一个结点到其他所有结点总共所花时间的最小值,所以可以采用Floyd算法求出每个结点到其他结点的最短路径,之后找到每个结点花的最长时间,再找到最小值即可:#include <iostream>#include <cstdio>#include <cstring>using namespace std;const int N = 110;const int INF = 9999;int dis[N][N];void Floyd(in.原创 2022-03-14 13:47:45 · 414 阅读 · 0 评论 -
【POJ】1502 MPI Maelstrom
题目大意就是找到第一个结点到其他结点最短距离的最大值,所以首先使用Dijkstra算法找到第一个结点到其他结点的最短距离,之后再找到最大值即可:#include <iostream>#include <cstdio>#include <string>#include <cstring>#include <vector>#include <queue>using namespace std;const int N =.原创 2022-03-13 18:41:37 · 575 阅读 · 0 评论 -
【POJ】2387 Til the Cows Come Home
求最短路径的基本题目,直接用Dijkstra算法即可:#include <iostream>#include <cstdio>#include <cstring>#include <vector>#include <queue>using namespace std;const int N = 1000 + 10;const int INF = 999999;struct Edge{ int to, length;.原创 2022-03-13 17:11:10 · 431 阅读 · 0 评论 -
【POJ】3258 River Hopscotch
该题目采用二分的思想:#include <iostream>#include <cstdio>#include <algorithm>using namespace std;const int N = 50000 + 10;int l, n, m;int dis[N];int main(){ while(cin >> l >> n >> m){ dis[0] = 0; d.原创 2022-03-12 16:53:40 · 146 阅读 · 0 评论 -
【POJ】1154 LETTERS
题目的大意是从第一行第一列的位置上开始移动问最远走多少步,直接采用DFS即可:#include <iostream>#include <cstdio>#include <cstring>#include <map>using namespace std;const int N = 30;int row, col, maximum;char matrix[N][N];map<char, bool> m;bool visit.原创 2022-03-12 11:11:51 · 123 阅读 · 0 评论 -
【POJ】1562 Oil Deposits
可以采用DFS的思想,对于每个油田判断其周围8个位置是否有油田,一直递归下去,然后计数即可:#include <iostream>#include <cstdio>#include <cstring>using namespace std;const int N = 100 + 10;int m, n, num;char matrix[N][N];bool oil[N][N];int pos[8][2] = {{1, 0}, {-1, 0}, {.原创 2022-03-11 17:32:08 · 159 阅读 · 0 评论 -
【POJ】3984 迷宫问题
使用DFS解决,1可以看成已经访问过的,0可以看成没有访问过的:#include <iostream>#include <cstdio>#include <vector>using namespace std;struct Edge{ int x, y; Edge(int x, int y): x(x), y(y){}};vector< vector<Edge> > v;int matrix[5][5];i.原创 2022-03-10 20:47:55 · 225 阅读 · 0 评论 -
【POJ】1321 棋盘问题
可以使用DFS遍历即可:#include <iostream>#include <cstdio>#include <cstring>using namespace std;const int N = 10;char matrix[N][N];bool visited[N][N];int num;bool isValid(int row, int col){ for(int i = 0; i < row; i++) .原创 2022-03-10 20:24:49 · 123 阅读 · 0 评论 -
【牛客网】KY139 毕业bg
关于贪心的使用————每个阶段的最优状态都是由上一个阶段的最优状态得到的那么该问题的状态和阶段是什么呢?现在来看关于阶段的定义,所谓阶段是指随着问题的解决,在同一个时刻可能会得到的不同状态的集合。我们可以把时间作为划分阶段的尺度,那么就是第i小时,就是第i阶段。因为本题要求最大快乐度,那么状态的对象一定是最大快乐度,既然阶段是时间,那么怎么定义才能让一个阶段包含多个不同状态的集合,那就是参加的不同活动的集合所带来的最大快乐度,对于本题,在一个给定的时间i可能一个人参加了活动1,但他同样能通过.原创 2022-03-02 17:36:56 · 232 阅读 · 0 评论 -
【牛客网】KY134 最大报销额
根据题意,首先找到符合条件的发票总额,然后使用DFS找到最大值即可:#include<iostream>#include<cstdio>#include<cstring>#include<vector>using namespace std;int n, m;double Q, maximum = 0;void dfs(vector<double> v, int index, double sum){ maximum.原创 2022-03-02 16:23:37 · 227 阅读 · 1 评论 -
【AcWing】4. 多重背包问题 I
多重背包问题,需要对数据进行分解,将其转换为0-1背包问题:#include <iostream>#include <cstdio>using namespace std;const int N = 1000 + 10;int w[N], v[N], k[N], weight[N], value[N], dp[N];int main(){ int n, m; while(scanf("%d%d", &n, &m) != EOF){.原创 2022-03-02 08:40:52 · 213 阅读 · 0 评论 -
【LeetCode】22. 括号生成
DFS加上一些剪枝策略:class Solution {public: map<string, bool> m; vector<string> generateParenthesis(int n) { vector<string> v; Func(v, "", 0, 0, n); return v; } void Func(vector<string> &v, str.原创 2022-03-01 21:29:16 · 56 阅读 · 0 评论 -
【LeetCode】11. 盛最多水的容器
我们最容易想到的方法就是设置两个指针依次遍历所有情况,然后找到最大的那个,但是这种方法的时间复杂度为O(n2),最后运行的结果会超时,因此需要另一种更好的方法。思路:一开始两个指针一个指向开头一个指向结尾,此时容器的底是最大的,接下来随着指针向内移动,会造成容器的底变小,在这种情况下想要让容器盛水变多,就只有在容器的高上下功夫。 那我们该如何决策哪个指针移动呢?我们能够发现不管是左指针向右移动一位,还是右指针向左移动一位,容器的底都是一样的,都比原来减少了 1。这种情况下我们想要让指针移动后的容器面积增.原创 2022-03-01 16:08:26 · 126 阅读 · 0 评论 -
【牛客网】DP31 【模板】完全背包
第一行的输出就是典型的完全背包问题,而第二行则是要求体积固定价值最大,因此需要先将dp2初始化为int类型所能表达的最小值,并将dp2[ 0 ]赋值为0。#include<iostream>#include<cstdio>#include<climits>using namespace std;const int N = 1000 + 10;int v[N], w[N], dp1[N], dp2[N];int main(){ int n, .原创 2022-03-01 15:55:13 · 155 阅读 · 0 评论 -
【牛客网】DP30 【模板】01背包
第一行的输出就是典型的0-1背包问题,而第二行则是要求体积固定价值最大,因此需要先将dp2初始化为int类型所能表达的最小值,并将dp2[ 0 ]赋值为0。#include<iostream>#include<cstdio>#include<climits>using namespace std;const int N = 1000 + 10;int w[N], v[N], dp1[N], dp2[N];int main(){ int n,.原创 2022-03-01 15:37:44 · 100 阅读 · 0 评论 -
【牛客网】KY41 放苹果
利用动态规划求解。当m >= n时,要么每个盘子至少有一个苹果,要么至少有一个空盘子,所以dp[ i ][ j ] = dp[ i ][ j - 1 ] + dp[ i - j ][ j ]。当m < n时,则至少有n - m个盘子空着,即最多有m个盘子有苹果,所以dp[ i ][ j ] = dp[ i ][ i ]。边界条件,当只有一个盘子或者没有苹果的时候,只有一种放法。#include<iostream>#include<cstdio>using .原创 2022-03-01 15:18:49 · 527 阅读 · 0 评论 -
【POJ】1163 The Triangle
这道题需要利用动态规划来求解,可以先利用matrix[][]存储三角形,然后dp[ i ][ j ]代表从( i , j )点出发到达底部路径之和的最大值,则dp[ 0 ][ 0 ]即为问题的解。对应的状态转换方程为:dp[ i ][ j ] = max(dp[ i + 1 ][ j ], dp[ i + 1 ][ j + 1 ]) + matrix[ i ][ j ]#include <iostream>#include <cstdio>#include <cs.原创 2022-03-01 14:25:16 · 474 阅读 · 0 评论 -
动态规划中的背包问题总结
背包问题是动态规划中的一种经典题型, 背包问题的变体繁多且复杂,这里总结一下背包问题中的0-1背包、完全背包以及多重背包三类问题。0-1背包问题描述:有n件物品,每件物品的重量为w[ i ],价值为v[ i ],现在有容量为m的背包,问如何选择物品使得装入背包的物品价值总量最大。对于这种问题,我们首先想到的就是遍历所有的情况,然后找到其中价值总量最大的,但是这个方法的时间复杂度为O(2n),复杂度太高了,因此需要用动态规划来求解该类问题,则可以使得时间复杂度降为O(nm)。首先设置一个二维数组dp[原创 2022-03-01 13:41:59 · 1131 阅读 · 0 评论 -
【POJ】1384 Piggy-Bank
这是完全背包问题求最小值,其状态转移方程为:dp[ j ] = min(dp[ j ], dp[ j - w[ i ] ] + v[ i ])#include <iostream>#include <cstdio>#include <climits>using namespace std;const int N = 1e4 + 10;int main(){ int t, e, f, n, v[N], w[N], dp[N]; sc.原创 2022-03-01 10:49:28 · 231 阅读 · 0 评论 -
【牛客网】KY14 最小邮票数
这是0-1背包问题的变形,0-1背包问题求最大值,这个求最小值,同时每件物品的价值都是1,其状态转移方程为:dp[ j ] = min(dp[ j ], dp[ j - w[ i ] ] + 1)#include<iostream>#include<cstdio>using namespace std;const int N = 100 + 10;int main(){ int m, n, w[N], dp[N]; while(scanf("%.原创 2022-03-01 10:19:49 · 158 阅读 · 0 评论 -
【牛客网】KY75 采药
典型的0-1背包问题,其状态转移方程为:dp[ j ] = max(dp[ j ], dp[ j - weight [ i ] ] + value [ i ])#include<iostream>#include<cstdio>using namespace std;const int N = 1000 + 10;int main(){ int t, m, weight[N], value[N], dp[N]; while(scanf("%d%.原创 2022-03-01 10:08:02 · 215 阅读 · 0 评论 -
【牛客网】KY114 Coincidence
最长公共子序列问题:#include<iostream>#include<cstdio>#include<string>using namespace std;const int N = 100 + 10;int dp[N][N];int main(){ string str1, str2; while(cin>>str1>>str2){ str1 = " " + str1; .原创 2022-02-28 21:28:18 · 86 阅读 · 0 评论 -
【牛客网】KY73 合唱队形
思路:除第一个和最后一个以外,以每个数为中间数。求此数的左边最大升序子序列的长度dp1[ i ],以及右边最长降序子序列的长度dp2[ i ],最少出列数应为min( n - dp1[ i ] - dp2[ i ] + 1)的值#include<iostream>#include<cstdio>#include<climits>using namespace std;const int N = 100 + 10;int main(){ int .原创 2022-02-28 21:06:05 · 192 阅读 · 0 评论 -
【牛客网】KY78 最大上升子序列和
对应的状态转移方程为:dp[ i ] = max (arr[ i ], dp[ j ] + arr[ i ] | j < i && arr[ j ] < arr[ i ])#include<iostream>#include<cstdio>using namespace std;const int N = 1000 + 10;int main(){ int n, arr[N], dp[N]; while(scanf(.原创 2022-02-28 20:45:18 · 176 阅读 · 0 评论 -
【牛客网】KY77 拦截导弹
求最长不增子序列与求最长递增子序列类似,只是状态转移方程有区别:dp[ i ] = max (1, dp[ j ] + 1 | j < i && arr[ j ] >= arr[ i ])#include<iostream>#include<cstdio>using namespace std;const int N = 30;int main(){ int n, arr[N], dp[N]; while(scanf.原创 2022-02-28 19:15:31 · 248 阅读 · 0 评论 -
【牛客网】KY141 最大连续子序列
利用的是求连续最大子序列和的办法:(1)当前面最大子序列和为负数的时候,后面的加上其一定会比后面本身更小,所以把sum置为0,重新寻找连续最大子序列和(2)重新寻找的时候,也就是新序列开始的时候,记录下此时的数,可能是最大连续子序列和的开始数(3)当新的连续最大子序列和大于之前的,说明之前的子序列不是所求,则更新序列的开始数和结尾数#include<iostream>#include<cstdio>#include<climits>using names.原创 2022-02-28 18:45:49 · 113 阅读 · 0 评论 -
【牛客网】KY63 最大子矩阵
要求一个二维矩阵的最大子矩阵,首先要会求一维矩阵的最大子矩阵(即一维数组连续最大和)假设原二维矩阵的最大子矩阵所在的行为i到j当 i = j 时,则最大子矩阵为第 i 行的连续最大和当 i != j 时,现在我们已经知道最大子矩阵的行,要求的是其所在的列我们把从第 i 行到第 j 行的所有行相加,得到一个只有一行的一维数组,则该一维数组的连续最大和就是最大子矩阵。这里有个小技巧是,可以先利用一个temp二维数组存储matrix每一行累加的结果,然后只需要执行temp[ j ] [ k ] -.原创 2022-02-28 13:05:32 · 286 阅读 · 0 评论 -
【牛客网】JZ49 丑数
通俗易懂的解释:首先从丑数的定义我们知道,一个丑数的因子只有2,3,5,那么丑数p = 2 ^ x * 3 ^ y * 5 ^ z,换句话说一个丑数一定由另一个丑数乘以2或者乘以3或者乘以5得到,那么我们从1开始乘以2,3,5,就得到2,3,5三个丑数,在从这三个丑数出发乘以2,3,5就得到4,6,10,6,9,15,10,15,25九个丑数,我们发现这种方***得到重复的丑数,而且我们题目要求第N个丑数,这样的方法得到的丑数也是无序的。那么我们可以维护三个队列:(1)丑数数组: 1乘以2的队列:2.原创 2022-02-28 09:52:42 · 87 阅读 · 0 评论 -
【牛客网】KY8 整数拆分
思路一:记f(n)为n的划分数,我们有递推公式:f(2m + 1) = f(2m),f(2m) = f(2m - 1) + f(m),初始条件:f(1) = 1。证明:证明的要点是考虑划分中是否有1。记:A(n) = n的所有划分组成的集合,B(n) = n的所有含有1的划分组成的集合,C(n) = n的所有不含1的划分组成的集合,则有: A(n) = B(n)∪C(n)。又记:f(n) = A(n)中元素的个数,g(n) = B(n)中元素的个数,h(n) = C(n)中.原创 2022-02-27 15:50:37 · 765 阅读 · 0 评论 -
【牛客网】JZ57 和为S的两个数字
因为是有序递增数组,因此可以采用左右夹逼的方法解决,即设置左右指针,若array[left] + array[right] == sum,则直接返回若array[left] + array[right] > sum,则需要将right减小,让整体的和减小若array[left] + array[right] < sum,则需要将left增大,让整体的和增大class Solution {public: vector<int> FindNumbersWithSu.原创 2022-02-27 11:10:53 · 149 阅读 · 0 评论 -
【牛客网】JZ36 二叉搜索树与双向链表
代码:/*struct TreeNode { int val; struct TreeNode *left; struct TreeNode *right; TreeNode(int x) : val(x), left(NULL), right(NULL) { }};*/class Solution {public: TreeNode* getRight(TreeNode *root){ //找到最右边的结点 if(!root) return nullp.原创 2022-02-27 10:22:39 · 227 阅读 · 0 评论 -
【牛客网】JZ31 栈的压入、弹出序列
思路:借用一个辅助的栈,遍历压栈顺序,先将第一个放入栈中,这里是1,然后判断栈顶元素是不是出栈顺序的第一个元素,这里是4,很显然1≠4,所以我们继续压栈,直到相等以后开始出栈,出栈一个元素,则将出栈顺序向后移动一位,直到不相等,这样循环等压栈顺序遍历完成,如果辅助栈还不为空,说明弹出序列不是该栈的弹出顺序。class Solution {public: bool IsPopOrder(vector<int> pushV,vector<int> popV) { .原创 2022-02-26 20:03:51 · 235 阅读 · 0 评论 -
【牛客网】JZ39 数组中出现次数超过一半的数字
方法一:先排序,因为一定有解,所以排序后中间元素一定就是出现次数超过一半的数字:class Solution {public: int MoreThanHalfNum_Solution(vector<int> numbers) { sort(numbers.begin(), numbers.end()); return numbers[numbers.size() / 2]; }};方法二:利用哈希:class Solution {.原创 2022-02-25 17:21:02 · 137 阅读 · 0 评论 -
【牛客网】JZ28 对称的二叉树
递归方法核心思想就是,左子树的左子树等于右子树的右子树,左子树的右子树等于右子树的左子树:/*struct TreeNode { int val; struct TreeNode *left; struct TreeNode *right; TreeNode(int x) : val(x), left(NULL), right(NULL) { }};*/class Solution {public: bool isSy..原创 2022-02-25 11:11:23 · 133 阅读 · 0 评论 -
【牛客网】JZ23 链表中环的入口结点
思路:设置快慢指针,都从链表头出发,快指针每次走两步,慢指针一次走一步,假如有环,一定相遇于环中某点(结论1)。接着让两个指针分别从相遇点和链表头出发,两者都改为每次走一步,最终相遇于环入口(结论2)。以下是两个结论证明:设置快慢指针,假如有环,他们最后一定相遇。两个指针分别从链表头和相遇点继续出发,每次走一步,最后一定相遇与环入口。证明结论1:设置快慢指针fast和low,fast每次走两步,low每次走一步。假如有环,两者一定会相遇(因为low一旦进环,可看作fast在后面追赶low的过程.原创 2022-02-25 09:49:02 · 89 阅读 · 0 评论 -
【牛客网】JZ44 数字序列中某一位的数字
数学分析:小于10,1-9,9个数字,9 位小于100,10-99,90个数字,180位小于1000,100-999,900个数字,2700位各个区间的上下线[0,10),[10,100),[100,1000) 位数是1,2,3。。。解题步骤:先确定第n个数在哪个区间内;再确定这个数属于哪个自然数;最后所在自然数得出数字;class Solution {public: /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 .原创 2022-02-24 16:35:35 · 237 阅读 · 0 评论 -
【牛客网】JZ15 二进制中1的个数
简单思路:首先将十进制数据转换为二进制数据,然后统计1的个数:class Solution {public: int arr[32]; void Divide(int n){ int index = 31; while(n){ arr[index--] = n % 2; n /= 2; } } int NumberOf1(int n) { memset(ar.原创 2022-02-24 15:47:09 · 131 阅读 · 0 评论 -
【牛客网】JZ86 在二叉树中找到两个节点的最近公共祖先
代码:/** * struct TreeNode { * int val; * struct TreeNode *left; * struct TreeNode *right; * }; */class Solution {public: /** * * @param root TreeNode类 * @param o1 int整型 * @param o2 int整型 * @return int整型 */ ..原创 2022-02-24 09:45:03 · 288 阅读 · 0 评论