
获得徽章 17
- leetcode 78 子集
思路1: 枚举
逐个枚举待组装元素,然后让幂集中的每个集合,追加这个待组装元素,就是新增的子集。
* 待组装元素: a b c
* 幂集: 空集
* 幂集: 空集 a
* 幂集: 空集 a b ab
* 幂集: 空集 a b ab c ac bc abc
思路2: 枚举格雷玛
思路:
比如 有 abc , 则从[1, 2^3-1]的每一个二进制数表示一种组合情况
-----
a b c
0 0 1
0 1 0
0 1 1
1 0 0
1 0 1
1 1 0
1 1 1
------
则所有的组合情况有: [a, b, ab, c, ac, bc, abc]
所以只需要枚举每个二进制数, 然后把这个二进制数生成对应的组合即可
比如 011 生成 ab
思路3: 深搜+回溯
常规深搜模版,深搜的时候选择路径就行了,选择完后就回溯方便下一次迭代继续进行深搜路径展开评论点赞 - # leetcode72 编辑距离
思路:
1、状态:
dp[i][j] 表示以i结尾的单词A 转成以j结尾的单词B 最小编辑距离
2、递推方程
假设两个单词 A: ***i 和 B: ***j , 则从单词 A 转成 单词B的 编辑距离以下编辑情况:
当A[i] == B[j] 时不需要编辑, 所以状态同上一步
dp[i][j] = dp[i-1][j-1]
当 A[i] != B[j]时 需要进行编辑:并且有三种编辑情况
a)、替换编辑
从状态dp[i-1][j-1] 开始编辑, 表示 对 i 或者 j进行一次替换操作即可编辑完成
b)、删除操作
从状态dp[i-1][j] 开始编辑, 也就是 A的 *** 部分变成B的 ***j 部分是已知的, 则此时A编辑后是****ji, 所以只需要删除一次i 即可编辑完成与B一致。
c)、增加操作
从状态dp[i][j-1]开始编辑,也就是 A的 ***i部分 变成B的***部分是已知的, 则此时A编辑后是 ***, 所以只需要增加一次 j 即可编辑完成与B一致。
所以 dp[i][j] = min(dp[i-1][j-1], dp[i-1][j], dp[i][j-1]) + 1
3、初始状态
增加空行,然后从空开始递推第一行和第一列的状态, 从空变成有 和 从有变成空 就是增加操作 和 删除操作。如下图:
"" r o s
-----------------
"" | 0 | 1 | 2 | 3 |
-----------------
h | 1 | | | |
----------------
o | 2 | | | |
----------------
r | 3 | | | |
----------------
s | 4 | | | |
----------------
e | 5 | | | |
----展开赞过评论1 - #leetcode 5. 最长回文子串
思路: 动态规划
1、状态定义: dp[a:b] 表示区间[a,b]的是否是回串
2、递推公式:
2.1) 当s[i] != s[j] 时,dp[i][j] = false
2.2) 当 s[i] == s[j]时,
如果 下标i 与 j相同 (比如 a ) 或者 下标i 与 j相差为1 (比如 aa) 则 dp[i][j] 为true。
如果下标:i 与 j相差大于1的时, 只需要看 dp[i + 1][j - 1]是否为true即可。 比如 abccba ,只需要看 bccb 区间的状态即可。
3、初始状态:
默认全部初始状态一定为false
4、递推顺序:
因为 i和j的 状态需要依赖于 i+1 和 j-1的状态, 所以递推顺序就是从下到上,从左到右来递推
---------------
| - | - | - |
---------------
| | - | - |
---------------
| | | - |
---------------展开赞过11 - leetcode: 239. 滑动窗口最大值
思路1: 暴力, 固定窗口滑动O(N^2)
定义窗口左右边界,然后直接滑动,然后直接一层循环求窗口内的最大值即可。
思路2: 对如何获取窗口内的最大值进行优化
使用一个双端队列(队头大,单调递减队列) 去维护窗口内的所有元素及其顺序,这样就能O(1)获取最大值
2.1) 如何维护这个双端队列
这个双端队列需要存储窗口内的所有元素, 并且按照从大到小的顺序排列,
假设已经存在队列(左边是队头,值大到小) : [a,b,c,d] , 现在窗口滑动后需要加入一个元素e
这时候我们需要找到e在队列中的位置并插入进去, 因为队列本身是有序的,只需要从队尾开始往前找即可, 又因为其实当窗口内准备加入一个元素e后, 其实窗口内比e小的元素已经没有必要再维护了, 直接在队列中删除掉即可, 所以最后的逻辑就是 把队列中国呢所有比e小的元素都删除掉,然后再把e插入队尾即可, 假设c和d都小于e, 先删除c和d再把e插入队尾即可,最后变成[a,b,e]. 维护成功后就可以方便的获取窗口内的最大值了展开赞过评论2 - 594. 最长和谐子序列
思路1: 排序 + 滑动窗口. 时间复杂度 O(NlogN)
先对nums排序, 然后 定义窗口[i,j], 枚举每一个窗口右边界为j的, 即使用右边界去滑动窗口. 滑动过程中, 如果发现窗口差值过大, 则需要缩小窗口差值, 则左边界要++, 直到窗口差值小于等于1. 然后判断窗口差值是否为1, 如果是计算窗口长度, 否则说明窗口差值过小,则继续扩大右边界,即j++
思路2: 找规律 + 哈希表 + 计数。 时间复杂度 O(N)
这里有一个隐性的规律,就是符合条件的子序列排序后 一定是这样的 [a,...a,a+1,a+1...a+1]
所以如果子序列右边界为nums[i], 则满足条件的子序列左边界一定是nums[i]-1, 所以此时只需要知道 nums[i]的个数 和 nums[i]-1的个数, 就可以知道子序列的长度, 所以需要先对nums计数.展开赞过评论1