算法学习
文章平均质量分 73
记录自己的日常算法学习
月亮的-影子
努力学习,相信未来
展开
-
两个字符删除操作总结
1.两个字符串的删除操作动态规划思路这个思路和LCS不一样,主要是子问题的定义不一样。对于LCS来说,dp[i] [j]的意思其实就是前i字符串word1和前j的字符串word2最大的子序列数。对于这道题来说就是前i的word1和前j的word2最小的删除数。不同的定义自然处理也是不相同的。但是这两种解法看上去就是反面,如果需要删除的话那么就是+1如果不需要删除那么就是-1。对于最长子序列来说是只要相同那么就去+1。也就是这道题统计的是最小的删除数达到最大子序列,这就是他们相似的地方。你会发现原创 2021-10-27 17:23:53 · 228 阅读 · 0 评论 -
编辑距离总结
1.编辑距离动态规划思路(自底向上)这道题其实和前面的两个字符删除操作极其的相似,只不过是状态需要好好地捋清楚。dp[i] [j]这里的i的意思就是word1前i个字符,word2前j个字符,如果要把word1改成word2所需要的最少操作。这里的把word1改成word2非常重要,必须理清楚关系是word1改成word2,重要的事说三遍。知道这个之后后面的状态转移才有可能捋清楚如果word1[i]==word[j]那么就可以什么都不做如果不相等就会有三种情况dp[i] [j原创 2021-10-27 17:23:33 · 260 阅读 · 0 评论 -
买卖股票问题系列总结
目录1.买卖股票的最佳时机暴力搜索贪心解决动态规划思路2.买卖股票的最佳时机 II暴力搜索思路动态规划思路贪心解法3.买卖股票的最佳时间3动态规划4.买卖股票的最佳时间3动态规划5.买卖股票时机含冷冻期动态规划6.买卖股票的最佳时机含手续费动态规划思路1.买卖股票的最佳时机暴力搜索因为只是要一天的,意思就是只要挑一天最小的买入,最大的卖出就可以了,转换过来就是求数组中的两个数最大的差值(前提是下标大的减下标小的,下面遍历就会看出来),那么只需要双指针,一个指向买入那天,然后另一个往后面找,后面那天的股原创 2021-10-24 19:08:47 · 264 阅读 · 2 评论 -
打家劫舍系列题目总结
1.打家劫舍思路常规的动态规划题目①dp[i]的意思是偷第i间房子的最大金额数②递推dp[i]=max(dp[i-1],dp[i-2]+nums[i]),其实就是求第i间房子最大金额,就是要么偷这间房,要么不偷,如果偷,那么前一个不能偷,也就是找dp[i-2]的最大金额+当前可以偷的nums[i]。如果不偷,那么最大金额就是从上一间房子得出。因为到第i间没变化,直接参照上一间就可以了(因为都是最大)。③初始化dp[0]肯定是nums[0],但是第二间房肯定就是从nums[0]和nums[1]中选择原创 2021-10-24 19:07:59 · 320 阅读 · 2 评论 -
动态规划入门题、背包类题总结
动态规划背包类总结1.斐波拉契2.爬楼梯3.使用最小花费爬楼梯4.不同路径5.不同路径26.整数拆分7.不同二叉搜索树8.背包理论9.分割等和子集10.最后一块石头的重量211.目标和12.一和零13.518. 零钱兑换 II14.组合总和415.爬楼梯(进阶)16.关于爬楼梯和零钱兑换 II17.零钱兑换18.完全平方数19单词拆分1.斐波拉契思路①dp[i]斐波拉契第i个值,i就是第i个数值②递推公式dp[i]=dp[i-1]+dp[i+1]③初始化前面两个0和1④遍历顺序是从前到后⑤举例原创 2021-10-17 01:01:50 · 153 阅读 · 0 评论 -
回溯题目总结
回溯题目总结(录哥题集)文章目录1.组合2.组合总和33.电话号码和数字总和4.组合总和5.组合总和26.分割回文串7.复原ip地址8.子集9.子集210.递增子序列11.全排列12.全排列213.重新安排行程14.n皇后15.解数独1.组合思路①回溯,但是需要注意的是这里需要的是组合,也就是说数字没有任何顺序,只要是同k个数字就是同一个集合。为了避免重复,所以每次进入下一层递归的时候都是继续+1遍历。而不是从头遍历到尾。终止条件是当path的大小==k的时候。本质上是多叉树的遍历。class S原创 2021-10-11 00:04:22 · 140 阅读 · 0 评论 -
贪心题目总结
贪心题目总结(录哥题集)文章目录1.分饼干2.摆动序列3.最大子序和4.买卖股票的最佳时机25.跳跃游戏16.跳跃游戏27.k次取反之后最大化数组和8.加油站9.分发糖果10.柠檬水找零11.根据身高重建队列12.用最少的数量的箭引爆气球13.无重叠区间14划分字母区间15.合并区间16.单调递增的数字17.买卖股票的最佳时机含手续费18.监控二叉树1.分饼干思路小饼干喂给小胃口。大饼干喂给大胃口。小饼干喂给小胃口的时候一定是第一块不行那么立刻转换第二块而不是第一块一直往下喂,由于从小到大所以是无法原创 2021-10-11 00:03:24 · 92 阅读 · 0 评论 -
二叉树题目总结
1.树的迭代遍历前序遍历思路用栈作为存储结构。每次都是先把根节点放进去,然后把根节点取出,然后就是把根节点的右子节点放进去,再放左子节点。那么下次取出来的就是左子树的根节点,再把左子树的右子节点放进去,再放左子树的左子节点。如此类推。就发现它的处理顺序是中左右。只有先放根节点进去,取出根节点,再放右子节点,和左子节点,就能够保证处理的顺序是前序遍历的顺序。class Solution { public List<Integer> preorderTraversal(TreeN原创 2021-10-08 16:57:13 · 309 阅读 · 1 评论 -
队列与栈题目总结
卡哥算法打卡1.用栈实现队列思路只用一个栈很明显就是不行的,需要两个栈。stack1和stack2。push操作比较简单,跟之前没有区别。但是pop就不同了,如果发现stack2是空的时候需要把stack1中所有的元素pop出来放到stack2里面,那么stack2中的元素pop出来就是队列的排序。但是只有stack2为空的时候才能够把stack1中的元素拿过来,原因就是如果不为空的情况也拿出来,就会压住上面的元素,导致顺序错误class MyQueue { Stack<Inte原创 2021-10-02 17:08:21 · 90 阅读 · 0 评论 -
双指针题目总结
(卡哥双指针篇打卡)1.移除元素思路可以直接暴力求解。但是时间复杂度会很大。有个更简单的办法就是快慢指针。这种快慢指针的思路就是,slow指针指向插入字符位置(把数组当成新的一个数组),fast指针指向需要验证的字符上。相当于就是fast往后面验证字符是否等于val如果是那么fast往后走,slow不需要进行插入val和往后走。如果不是那么fast还是往后面走,但是slow需要插入val并且往后面走class Solution { public int removeEle原创 2021-09-30 20:39:29 · 120 阅读 · 0 评论 -
子集、组合、排列、数独回溯问题
子集、组合、排列问题这几个问题的解法都是可以使用回溯算法的,而回溯算法其实就是在求树的遍历。而这几个问题就是在提升这方面的能力。首先是子集问题。给你一个数组来求它的所有的子集,而子集是不能有重复的,比如[1,2]和[2,1]是重复的,求子集的方法可以通过回溯算法,而且每次遍历的时候都要按照一定的顺序。比如数组[1,2,3]以1开头的子集是[1]、[1,2]、[1,3],以2开头的子集[2]、[2,3],然后以3开头的子集就是[3],那么这样来凑子集是不会有重复的元素的,我们只需要调整一下每次递归回溯的开原创 2021-03-13 00:07:11 · 177 阅读 · 0 评论 -
链表的几个问题
链表的几个问题(labuladong算法小抄总结)第一个问题就是判断回文链表首先我们得知道怎么样来寻找回文串,寻找回文串的思路其实并不难,就是从中间开始往外面扩展判断。String palindrome(String s,int l,int r){ while(l>0&&r<s.length() &&s.charAt(l)==s.charAt(r)){ l--;r++; } return s.substring(l+1,原创 2021-02-19 11:21:38 · 104 阅读 · 0 评论 -
单调队列maxSlidingWindow
单调队列maxSlidingWindow(labuladong算法小抄3.8总结)maxSlidingWindow是力扣的239题。这道题考察的是一个单调队列。相对来说是比较困难的一道题,难度在于你需要在O(1)的复杂度下面完成这一道题是非常难的。直接遍历计算,时间复杂度就会非常高。那么这个时候就需要用到单调队列。那么什么是单调队列?单调队列其实就是队列的一种变体,在里面的数据都是单调的,而且可以通过一些操作来获取最值。class MontonicQueue{ private LinkedLi原创 2021-02-18 21:24:33 · 201 阅读 · 0 评论 -
单调栈nextGreaterElements
单调栈nextGreaterElements(labuladong算法小抄总结)这类型的问题都是考察单调栈的问题。那么什么是单挑栈呢?单调栈就是栈里面的数据是单调的。而正是这个特点才能够解决nextGreaterElements问题。第一个问题就是下一个更大元素1:这道题就是很经典的单调栈问题。其实可以把这个问题看成就是一个对比身高的问题,它求的是比当前值大的下一个值。也就是求比当前的人更高的下一个人。我们会很自觉地忽略掉那些后面比较矮的人,直接看到那些比较高的。而这里为什么可以使用到单调栈呢?因为原创 2021-02-18 19:53:35 · 170 阅读 · 0 评论 -
二叉树的最近公共祖先
二叉树的最近公共祖先(labuladong算法小抄3.6总结)这个问题需要知道就是p点和q点所在的位置。然后再根据这两个点的位置,来寻找他们最近的交叉点,也就是最近的公共祖先的位置。其实本质上还是一个树的遍历问题。但是不同的是它需要处理的情况比较多,代码不难,难的地方在于怎么找到这个交叉点。首先来思考一下,既然想要找到p和q的最近公共祖先,那么先要找到这两个点。然后找到两个点之后就需要通知上一层的树,告诉他我找到了这个点了,并且把本节点返回去了作为公共祖先的可能候选点。但实际上细分就是会有三种情况:原创 2021-02-17 22:33:47 · 215 阅读 · 0 评论 -
二叉树的序列化和反序列化
二叉树的序列化和反序列化(labuladong算法小抄总结)这里会介绍三种序列化和反序列化的方法。其实本质上就是树的遍历的过程中添加一些操作而已,只要心中有框架,那些添加的操作就会很简单,如果没有二叉树的遍历框架,会比较难想出来。首先第一种方法前序遍历:void traverse(root){ sout(root) traverse(root.left) traverse(root.right)}这个就是前序遍历的框架,序列化也只不过是修改了一下sout(root)这里罢了。原创 2021-02-17 21:46:44 · 437 阅读 · 1 评论 -
二叉树的操作以及完全二叉树的节点计算
二叉树的操作以及完全二叉树的节点计算(labuladong老师的题目总结)第一个问题在BST中寻找一个数首先我们普通的寻找就是每个节点都去遍历然后对比目标值,但是这样的复杂度是比较高的,而且没有使用到BST的特点左小右大。那么应该如何才能使用呢?这里就要提出一个BST的框架,我们可以通过每次对比一下target和我们根节点的值,然后选择左子树递归还是右子树递归,这样就减少一大半的遍历时间。寻找一个数的代码boolean isInBST(TreeNode root,int target){原创 2021-02-16 00:11:25 · 441 阅读 · 0 评论 -
判断二叉树的合法性
判断二叉树的合法性首先第一个问题就是什么样的二叉树具有合法性?简单来说就是所有节点的左子树都比节点小,右子树比节点大。必须遵守这一个规则这样的二叉树就是合法的。那么如何判断它是不是合法的呢?是不是可以直接来判断一下左子节点和节点还有右子节点的大小就可以了呢?当然是不可以的,你现在确定了节点的左子节点和右子节点符合规则,但你没办法确定左子树下面的节点是不是都符合规则,万一左子树下面有一个节点比本节点大,那么就是不符合规则的。也就是说我们不能够直接来解决这个问题。那么什么样的思路可以解决这个问题?我们原创 2021-02-15 22:34:50 · 686 阅读 · 0 评论 -
LFU算法
LFU算法(向labuladong老师学习的LFU)LFU算法是什么?有什么作用?LFU算法其实就是按照程序使用的次数频率来进行淘汰的算法,使用频率少就会被删除。它在程序过多的情况下,是一种很好的处理策略。那么LFU算法是如何实现的?LFU算法是比较复杂的,因为数据结构偏多,需要处理不只是一个数据结构,而是多个,所以容易忽略和写错。最好的办法就是从大看小,先把方法写出来,画出图,然后整理大逻辑,最后再落脚在小的细节上面。现在来从大体来说说它是如何实现的。freq:就是使用程序多少次的意思①第一原创 2021-02-14 23:31:37 · 1221 阅读 · 0 评论 -
LRU缓存淘汰算法
LRU缓存淘汰算法这是一个什么算法?这是一个可以处理程序过多的情况下该删除哪一个程序的算法策略。它是根据最近使用时间来进行确定的,通常删除的是最后一个节点。那么这个算法会涉及什么样的数据结构?这个算法涉及了HashMap和双向链表的数据结构,通过这两个结构的配合可以通过map来快速定位存取节点,通过双向链表来快速增删节点。首先我们来讲讲原生代码是如何实现的(这里参考的是labuladong老师的解法)其实原生代码的实现就是我们自己来创造一个双向链表,然后加上一个HashMap来配合算法的使用。双原创 2021-02-12 23:15:56 · 85 阅读 · 0 评论 -
目标和
目标和这里会提出两个思路来解这个问题。第一个思路就是回溯,而且最容易想到的思路也是回溯。第二思路比较难想到,非常巧妙。先讲讲回溯是怎么实现的吧。其实就是把所有的可能遍历一次,怎么样才能把所有可能遍历一次呢?我们先用最暴力的方法,数组每个数字要么正要么负,只需要把这些数与target相加减就能够得到0,相当于是数组的数字应该怎么组合正负才能让target最终变成0。数字的正负其实就是回溯中的选择,只拿相加来说,也就是target-num[i],其实就是倒着来想,我们不是要凑成target而是把targe原创 2021-02-12 00:21:33 · 82 阅读 · 0 评论 -
打家劫舍
打家劫舍力扣里面的打家劫舍有三个问题,每个问题都是层层递进的,从简单到难。(labuladong老师的书更详细,这里是我的思考总结)首先是第一个问题,是一个比较简单的动态规划问题,我们可以自顶向下来做这个问题。如何自顶向下思考呢?我们的问题是每个房子都有钱,抢了一间房子,那么相邻的房子就不能够抢了,求最大的获得钱数。首先这个问题就是一个最值的问题,而且每个问题都是最优子,我们就可以为他确定dp函数。首先我们要明确要求的是什么,求的是最大获得钱的数,那么我们dp(int[] nums,int n)的意思就原创 2021-02-11 22:18:34 · 94 阅读 · 0 评论 -
零钱兑换 II
零钱兑换 II零钱兑换 II是一个经典的完全背包问题。那么什么是完全背包呢?完全背包的意思是物品是可以无限使用的,背包仍然还是只能装载这么多。背包问题和完全背包问题的区别就是物品可使用次数,背包问题是只能使用一次,完全背包是不限次数。所以它们是非常相像的问题,只是细节上有一些不同。那么既然是一个完全背包问题,这个问题肯定就是一个动态规划问题。既然是动态规划肯定就需要涉及状态转移和选择问题。在这之前首先我们就需要定义dp[i][j],它的意思其实就是在只能选前i个硬币的面值的情况下,背包装满 j 金额的原创 2021-02-05 22:33:47 · 83 阅读 · 0 评论 -
分割等和子集
分割等和子集其实这道题和0-1背包的思路非常相似,如果没有做过背包问题这道题可能相对来说比较难,但是如果做过背包问题这道题就变得非常简单。首先我们来分析题目,我们需要求得两个和相同的子集,我们就会发现,如果两个子集的和相同,那么两个子集相加的结果就等于数组的和。这个条件有什么用呢?这样我们就能够分解问题,问题就变成了一个求和问题,我们能不能够在数组中找到一个子集的和等于sum/2对吧。而且两个子集相等是不是也说明了sum一定是一个偶数,所以sum%2==0。这个问题和背包问题有什么联系?想想我们原创 2021-02-02 23:41:02 · 138 阅读 · 0 评论 -
0-1背包问题
问题问的是有N个物品,背包可以装Wkg,现在已知物品的所有重量wt,和价值val。求最大价值的装法。这是一道很经典,也不算很难的动态规划问题。只需要理清楚状态和选择就可以了。那么状态是什么?选择又是什么?由于给定的重量和价值都是有序的,所以物品是可以按照一些顺序来进行装入。首先我们放入一个物品进背包的时候什么会发生改变?当然就是背包的容量和物品的个数了,背包是不是装多了一点东西?物品是不是减少了?对吧。那么我们就可以来定义dp数组的含义,dp[i][j]其实就是前i个物品中,装入能装 j 千克的背原创 2021-02-02 00:07:10 · 117 阅读 · 0 评论 -
戳气球问题
戳气球问题有 n 个气球,编号为0 到 n - 1,每个气球上都标有一个数字,这些数字存在数组 nums 中。现在要求你戳破所有的气球。戳破第 i 个气球,你可以获得 nums[i - 1] * nums[i] * nums[i + 1] 枚硬币。 这里的 i - 1 和 i + 1 代表和 i 相邻的两个气球的序号。如果 i - 1或 i + 1 超出了数组的边界,那么就当它是一个数字为 1 的气球。求所能获得硬币的最大数量。来源:力扣(LeetCode)链接:https://leetcode-原创 2021-02-01 23:28:25 · 158 阅读 · 0 评论 -
高楼扔鸡蛋(重新定义的状态转移)
高楼扔鸡蛋(重新定义的状态转移)正常来说高楼扔鸡蛋想到二分解法的时候就已经想破脑袋了。但是还有一种更难的想到,而且即使知道这种想法,也很难把思路理清楚,因为真的特别绕。不过难是难,但是努力去往这个想法去靠近总会越来越接近答案的。现在就给出这个解法的思路。重新定义高楼扔鸡蛋的dp数组dp[k][m]原本这里的定义是有k个鸡蛋,n层楼,最坏的情况下最少的扔鸡蛋个数。虽然有点绕但是仔细思考也能够理清思路。而重新定义的dp[k][m]就换了一种说法,有k个鸡蛋,只允许你扔m次鸡蛋,在最坏的情况下最多能够测试多原创 2021-01-31 09:24:14 · 192 阅读 · 2 评论 -
高楼扔鸡蛋问题(二分解法)
高楼扔鸡蛋问题(二分解法)二分解法是基于高楼扔鸡蛋的基本动态规划解法。今天就来讲一下高楼扔鸡蛋的第二种解法,二分解法。其实并不是特别难,只不过换了一种遍历的方式。我们继续看一下这个问题,为什么可以使用二分解法?为什么这道题符合二分搜索的要求?其实我们只要仔细观察这道题就会发现,我们原来定义的dp[k][n]在有k个鸡蛋,n层楼的最坏情况下扔鸡蛋的最少数目是会随着楼层的减少,扔鸡蛋的次数也会减少。原理很简单。。,你看少了一层楼,那么假设现在有6层楼,我们第一种方案就是一层一层的扔,最坏情况就是扔6次,如原创 2021-01-25 21:20:09 · 608 阅读 · 0 评论 -
高楼扔鸡蛋问题
高楼扔鸡蛋问题这个问题问的是有N层楼,K个鸡蛋,有第1<=F<=N层楼鸡蛋刚好不碎,最坏情况下至少扔多少次鸡蛋?对于这道问题比较难的就是理解题目的意思,穷举的本身和代码并不难,但是理解题目,解析出来比较难。现在我来谈谈自己对这道题目的思考。如果有不正确的地方希望大家能够指出。1.首先我需要抛出问题①什么是最坏的情况如何理解?②至少扔多少次鸡蛋在这道题又应该如何理解③为什么动态规划可以解决这道题现在我一个一个问题来解析。**最坏的情况什么意思?**现在举一个例子,在我们不考虑鸡蛋数目的原创 2021-01-21 22:22:12 · 183 阅读 · 0 评论 -
最大公共子序列长度的思考
最大公共子序列长度的思考我借鉴了挺多博主对这道题的看法,然后结合自己的思考整理了一下思路。对于我自己来说,这一道题非常的难,可能我是菜鸟的缘故,我是看过自顶向下的递归答案还有自底向上的思路求解,以及dp数组的一个定义进行的分析。我最开始最困惑的地方就是这里的递归解法,dp(i),j函数的i和j为什么会有两个意思,一个是代表两个字符串的指针,另一个意思就是字符串的长度。dp不都是解释为s1[0…j],s2[0…j]的最大子序列长度嘛。而我自己更偏向指针的思考。但后来发现两个都需要。我这里只讲思考所以就不贴原创 2021-01-20 00:28:48 · 96 阅读 · 0 评论