随笔分类 - 数据结构与算法
摘要:首先一个错误的暴力解法,加深对解空间结构的认识: /** * @Author Niuxy * @Date 2020/6/21 11:30 上午 * @Description 解决问题时先推导一下,问题是否可以被自己解决。 * 若果不行,尝试转化问题。 * 比如找出所有递增序列,并按长度计数 */ p
阅读全文
摘要:关键在于如何定义问题进行分治: 1. 问题的定义必须可以覆盖解空间。 2. 问题的解可由子问题的解表示,也就是状态转移关系。 划分问题,无非就是:按区间划分,找出区间与区间的关系,最后的问题覆盖整个问题入参区间;按点划分,找出点与点的关系,最后合并所有点的结果覆盖整个问题入参区间。 对于解题来说,无
阅读全文
摘要:public final int findLongestChain(int[][] pairs) { sort(pairs); int[] dp=new int[pairs.length]; dp[0]=1; int maxRe=0; for(int i=1;i<dp.length;i++){ in
阅读全文
摘要:暴力法没有什么技术含量,但暴力法包含着我们对解空间最基本但认识。不管什么题目,还是习惯最先用暴力的思路考虑一遍,再去考虑优化方式。 //最终结果 int an = 0; //路径计数 int tar = 0; public int deleteAndEarn(int[] nums) { tar=nu
阅读全文
摘要:LRU(最近最少使用) 缓存为一段固定大小的缓存,按最近最少使用的淘汰策略对数据进行管理。 一个 LRU 缓存应当支持 put 和 get 操作: 进行 get 操作时,发生 cache miss 返回固定标识。缓存命中在返回数据的同时更新最近使用时间。 进行 put 操作时,如果 key 存在则更
阅读全文
摘要:* @Description 问题为骑士跳 N 步有多少种跳法* 我们以步数 N 分割问题,此时发现,影响问题解的不只是步数,还在于骑士当前处在什么位置* 因为这决定了骑士下一步会不会越界* 所以我们以骑士所处的位置 x,y 以及剩余跳的步数 n 来定义问题* g(x,y,n) 表示处在 x,y 位
阅读全文
摘要:* @Description 从左上角开始移动,每次移动可以向右也可以向下* 问题本身自带状态转移关系,下一步状态基于上一步位置* 建立缓存时以位置为坐标,G(x,y) 表示从 x/y 坐标开始行动可以获取的最大价值* 因为有最大的含义, x/y 坐标可以唯一的确定 从本位置开始移动可获得的最大价值
阅读全文
摘要:首先暴力搜索: public final int maxSubArray1(int[] nums) { int max = Integer.MIN_VALUE; for (int i = 0; i < nums.length; i++) { for (int j = 0; j < nums.leng
阅读全文
摘要:看到题目,一个变种的八皇后,在矩阵中寻找路径。 关于回溯的思路在博客: Burst Balloons(leetcode戳气球,困难)从指数级时间复杂度到多项式级时间复杂度的超详细优化思路(回溯到分治到动态规划 ) 中有非常详细的描述。 本题优化时间复杂度的关键在于剪枝,当越界、字符不匹配、路径已走过
阅读全文
摘要:* @Description 将一条绳子剪成任意 m 段,m 大于 1 ,求最大积 * 决定问题规模的参数为绳子的长度 n * 按 n 进行分治,G( n ) 为长度为 n 的绳子分割后可得的最大积,可列出状态转移方程: * G( n ) = max { G(n-1)*1 , G(n-2)*2...
阅读全文
摘要:一道简单题目,DP 的递归表示竟然无法 AC,只能用递推表示。解题思路: * @Description nums 长度决定为题规模 * 按 nums 长度区间进行分治 * G(i) 代表前 i 个元素中可得的最大分钟数 * 因为题目要求,相邻元素不能选取,所以要确定 G(i-1) 与 G(i) 的关
阅读全文
摘要:题目非常简单,之所以记录一下是因为总是忽略中序遍历的特性:排序二叉树中序遍历会得到一个有序数组。该特性很实用也很神奇,就像一颗满二叉排序树的根节点必然是对应有序数组的中点一样。该特性可以帮助我们更好的理解排序树的结构。 List<Integer> re=new LinkedList<Integer>
阅读全文
摘要:很多清奇的解法不是靠拍脑袋一蹴而就的,而是随着传统解法一步一步优化来的。刷题时不需要经常焦虑自己没有创新毒辣的解题思路,应该从传统解法开始,考虑当前解法有什么可优化的点,并去实现它们。 最容易想到的自然是暴力法,我们假设每个元素都可以作为买入元素的前提下,再假设在其之后的每个元素尝试卖出,纪录最大差
阅读全文
摘要:两种解法,DFS 与 BFS ,均已通过。对于 DFS 来说,我们需要从右到左遍历所有节点,并在每次遍历时记录当前深度。如果当前深度与结果数组长度相同,则为该层可以右视到的节点: /** * @Author Nxy * @Date 2020/5/9 * @Description DFS 解法 */
阅读全文
摘要:最开始使用 DP ,因为题目中给的问题空间范围较大,缓存使用数组的话对连续的内存空间要求过高。故采用 hash 表做缓存: public int maxScore(int[] cardPoints, int k) { int length = cardPoints.length; Map<Strin
阅读全文
摘要:一个中等难度的 dp 题目,矩阵的长宽决定了问题规模的大小。问题的定义是在矩阵 A 中一层一层的下降,这个定义本身便具有最优子结构性质。 我们在第 i 层想要下降到 i+1 层有三种选择,走左边 j-1 ,走中间 j ,走右边 j+1 ,我们取三者的最小值即可。 设 G( i,j ) 为计算 从坐标
阅读全文
摘要:题目如上,一个背包类 dp 问题。感觉该题的解题思路算是相当经典了,小记一下。 做这个题有如下感悟: 1、dp 是一个运筹学问题,做题时不要忽略方程的本质:用小问题表示大问题,用函数表示函数。大问题可以用小问题表示,反过来,小问题的组合可以合并为大问题。在多维 dp 中要尤其注意,这可以帮助我们将一
阅读全文
摘要:题目如上。 我们假定,求从 nums 数组第 flag 位置开始目标和为 S 的组合数的函数为:G(nums, S, flag) 。 那么状态转移方程的表示为:G(nums, S, flag) = G(nums,S-nums[flag],flag+1) + G(nums,S+nums[flag],f
阅读全文
摘要:首先,我们假定求长度为 n 的数列可组成的二叉搜索树的数量为 G(n)。 想办法将 G(n) 用其子问题表示,如果我们以第 i 个元素为根,则其左子树的数量为 G(i-1),右子树的数量为 G(n-i) 。那么以第 i 个元素为根的二叉搜索树的数量为 G(i-1) 与 G(n-i) 两个集合的笛卡尔
阅读全文
摘要:又是一道简单题(最近项目事情多有点偷懒),不需要贪心、不需要分治、更不需要 DP,只要最简单的递推就可以解出的题目。但第一次提交没有通过,原因在于边界条件的考虑不到位,所以想要借机总结一下如何确定边界条件。 边界条件就想数学表达式中变量的取值范围,一个数学表达式的成立一定是有限制条件的,程序也是如此
阅读全文