0,1,2
分为三段:0段、未判定段、2段,用三个指针(s0, cur, s2)指向每一段的当前位置。
s0并不是指向0段的最后一个元素,而是指向最后一个元素的下一个元素。s2类似。
如果A[cur]=0,则s0(其实指向1),cur互换位置; s0++; cur++;
如果A[cur]=1,则cur++;
如果A[cur]=2,则s2,cur互换位置; s2—; cur不变;
0,1,2
分为三段:0段、未判定段、2段,用三个指针(s0, cur, s2)指向每一段的当前位置。
s0并不是指向0段的最后一个元素,而是指向最后一个元素的下一个元素。s2类似。
如果A[cur]=0,则s0(其实指向1),cur互换位置; s0++; cur++;
如果A[cur]=1,则cur++;
如果A[cur]=2,则s2,cur互换位置; s2—; cur不变;
有字符串,将所有连续的ac跟单独的b去掉后的字符串:如bbbacccccb->ccc; aacceacdby->edy
时间复杂度O(n) 空间复杂度O(n) —> 时间复杂度O(n) 空间复杂度O(1)
这是本题较好的一种解法,设两个指针cur和loc分别从头开始出发,cur每次移动一格,另一个指针loc保留当前的操作位置,如果cur指向的字符是c且loc指向的是a,则将loc回移一位(ac抵消了),如果遇到其他非b的字符,则将loc处的字符置为cur处的字符(++location),一直进行直到到cur到达字符串尾部,此时取字符串开头到loc指针之间的子串即为本题的解。这种解法妙就妙在loc处的字符是即时更新的,一些边界条件都自动消除了。
输入n个整数,输出出现次数大于等于数组长度一半的数。
输入描述:
每个测试输入包含n个空格分割的n个整数,n不超过100,其中有一个整数出现次数大于等于n/2。
输出描述:
输出出现次数大于等于n/2的数。
摩尔投票法的核心就是一一抵消,删除不同的数。
因为要找过半的数,用一个变量count记录读取每个变量变化的次数,一个变量temp记录可能过半的数。
先让count = 1,然后让temp = vec[0],然后往后遍历一遍。
碰到和temp相同的数就给count++,否则就count—,如果count变成0,就让temp=vec[i] (v数组遍历过程中的当前值),并让count = 1。
如此遍历一遍,因为有一个数过半,所以temp最后肯定存储的是过半的数
1 | class Solution { |
参考:
https://www.zhihu.com/question/284969980/answer/440979325
给定一个包含了一些 0 和 1 的非空二维数组 grid 。
一个 岛屿 是由一些相邻的 1 (代表土地) 构成的组合,这里的「相邻」要求两个 1 必须在水平或者竖直方向上相邻。你可以假设 grid 的四个边缘都被 0(代表水)包围着。
找到给定的二维数组中最大的岛屿面积。(如果没有岛屿,则返回面积为 0 。)
解题思路:
DFS
稠密图,邻接矩阵;
稀疏图,邻接表
1 |
|
1 | 树与图的遍历 |
1 | 拓扑排序 —— 模板题 AcWing 848. 有向图的拓扑序列 |
算法 | 解决的问题 | 算法原理 | 时间复杂度 |
---|---|---|---|
dijkstra | 单源最短路,稠密图, 正权 | 找到最小距离,用找到的最小距离更新剩余距离 | $O(N^2)$ N为图点的数量 |
堆优化版dijkstra | 单源最短路,稀疏图,正权 | 借助堆来优化dijkstra算法中的查找最小值操作 | $O(N^2)$N为图点的数量 |
bellman-ford | 单源最短路,负边权,限制步数的情形 | 迭代k次,每次找最小距离 | $O(N^2)$ N为图点的数量 |
SPFA | 单源最短路,负边权,判定有没有负环 | 队列优化 | $O(N^2)$ N为图点的数量 |
floyd | 多源汇最短路 | 动态规划思想,三角不等式 | $O(N^3)$ N为图点的数量 |
1 |
|
算法 | 解决的问题 | 算法原理 | 时间复杂度 |
---|---|---|---|
prim算法 | 单源最短路,稠密图, 正权 | 找到最小距离,用找到的最小距离更新剩余距离 | $O(N^2)$ N为图点的数量 |
kraskal算法 | 单源最短路,稀疏图,正权 | 并查集 | $O(N^2)$ N为图点的数量 |
1 |
|
如何判定图是不是二分图:DFS遍历,奇数环
二分图匹配:匈牙利算法
1 | 染色法判别二分图 —— 模板题 AcWing 860. 染色法判定二分图 |
Maximum sum such that no two elements are adjacent
Given an array of positive numbers, find the maximum sum of a subsequence with the constraint that no 2 numbers in the sequence should be adjacent in the array. So 3 2 7 10 should return 13 (sum of 3 and 10) or 3 2 5 10 7 should return 15 (sum of 3, 5 and 7).Answer the question in most efficient way.
Examples :
Input : arr[] = {5, 5, 10, 100, 10, 5}
Output : 110
Input : arr[] = {1, 2, 3}
Output : 4
Input : arr[] = {1, 20, 3}
Output : 20
遍历array 中的所有元素,设置两个变量:
excl[i]: 不包含i元素的最大和
incl[i]: 包含i元素的最大和
更新当前元素的 excl 和 incl:
不包含当前元素的最大和 excl[i] = max(incl[i-1], excl[i-1])
包含当前元素的最大和 incl = excl[i-1]+A[i] (元素不能相邻)
因为只与前一项有关,所以可以用空间压缩。
我们把只包含质因子2、3和5的数称作丑数(Ugly Number)。
例如6、8都是丑数,但14不是,因为它包含质因子7。
求第n个丑数的值。
样例
输入:5
输出:5
注意:习惯上我们把1当做第一个丑数。
第二种:创建数组保存已经找到丑数,用空间换时间的解法。
根据丑数的定义, 丑数应该是另一个丑数乘以 2、3 或者 5 的结果(1 除外)。因此我们可以创建一个数组,里面的数字是排好序的丑数,每一个丑数都是前面的丑数乘以 2、3 或者 5 得到的。
这种思路的关键在于怎样确保数组里面的丑数是排好序的。假设数组中已经有若干个丑数排好序后存放在数组中,并且把己有最大的丑数记做M,我们接下来分析如何生成下一个丑数。该丑数肯定是前面某一个丑数乘以 2、3 或者 5 的结果, 所以我们首先考虑把已有的每个丑数乘以 2。在乘以 2 的时钝能得到若干个小于或等于 M 的结果。由于是按照顺序生成的,小于或者等于 M 肯定己经在数组中了,我们不需再次考虑:还会得到若干个大于 M 的结果,但我们只需要第一个大于 M 的结果,因为我们希望丑数是按从小到大的顺序生成的,其他更大的结果以后再说。我们把得到的第一个乘以 2 后大于 M 的结果记为 M2,同样,我们把已有的每一个丑数乘以 3 和 5,能得到第一个大于 M 的结果 M3 和 M,那么下一个丑数应该是 M2、M3 和 M5 这 3 个数的最小者。
前面分析的时候,提到把已有的每个丑数分别都乘以 2、3 和 5。事实上这不是必须的,因为已有的丑数是按顺序存放在数组中的。对乘以 2 而言, 肯定存在某一个丑数 T2,排在它之前的每一个丑数乘以 2 得到的结果都会小于已有最大的丑数,在它之后的每一个丑数乘以 2 得到的结果都会太大。我们只需记下这个丑数的位置, 同时每次生成新的丑数的时候,去更新这个 T2。对乘以 3 和 5 而言, 也存在着同样的 T3 和 T5。
T2的更新是需要靠遍历来完成的,但是需要明确的是:T2不需要每次都从0开始,他是越来越大的。
求解一个矩阵中找一条最长的递增路径?
可能解法:有向图DFS和记忆化搜索处理
dp[i][j]表示以(i,j)出发的最长路径。
该题目用常规的DP很难完成,因为他没有base condition,不知道从何处开始计算。
给你一根长度为 n 绳子,请把绳子剪成 m 段(m、n 都是整数,2≤n≤58 并且 m≥2)。
每段的绳子的长度记为k[0]、k[1]、……、k[m]。k[0]k[1] … k[m] 可能的最大乘积是多少?
例如当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到最大的乘积18。
样例
输入:8
输出:18
自上而下 + 备忘录解法
1 | class Solution { |
在一个m×n的棋盘的每一格都放有一个礼物,每个礼物都有一定的价值(价值大于0)。
你可以从棋盘的左上角开始拿格子里的礼物,并每次向右或者向下移动一格直到到达棋盘的右下角。
给定一个棋盘及其上面的礼物,请计算你最多能拿到多少价值的礼物?
注意:
m,n>0
样例:
输入:
[
[2,3,1],
[1,7,1],
[4,6,1]
]
输出:19
解释:沿着路径 2→3→7→6→1 可以得到拿到最大价值礼物。
解题思路:
1 | class Solution { |