- 博客(52)
- 收藏
- 关注
原创 贪心算法:分发糖果
我们才更新,而不是无脑进行覆盖,这其实是一次取max的更新操作,因为第一次的遍历,已经让有些nums变大了,第二次我们遍历的时候,如果由于第一次的遍历,nums已经满足操作,我们就没必要更新其值,因为可能算出来的值反而更小,这样就把第一次的遍历的规则给破坏了。这里面,nums中8比7大,所以nums更新为2,但由于7比3大,所以7更新为2,导致8和7对应的糖果数量又相同了!这是由于遍历顺序的错误导致出现了“覆盖”的错误!因为我们改变的顺序应该和遍历的顺序相反!这下,“覆盖”的问题就解决了。
2025-02-25 14:52:23
274
原创 贪心算法:加油站
如果子数组加在一起的和为负数,那么他在加上下一个数只会让下一个数更小,所以单独算下一个数比加上前面的子数组更大。算子数组和的时候,需要把整个数组算完,并且如果起始点不是数组的第一个元素,需要一次内部的循环。
2025-02-24 19:23:08
225
原创 贪心算法:K次取反后最大化的数组和
我们先把数组排序,然后从左往右把所有负数都取反,如果负数的个数小于k,那么把剩余的次数全部消耗在数组最小的正数上,就可以实现相同的功能,无需排序k次。可是这样的时间复杂度太高了,因为我们每次取了反,就要重新排序一次,如何优化呢?如果我们每次都找最小的值对它进行取反,那么每次得到的结果都是最优解。所以我们可以进行排序,找到最小值(即第一个),取反。
2025-02-24 16:33:57
143
原创 贪心算法:跳跃游戏2
这题在基础版本的基础上,需要找到最小的跳跃次数,也就是我们要:找到范围内,能跳跃最远的点(比基础版多了一个记录新起始点的过程以下面举例:当我们访问nums[0],下一个节点如何找呢?我们能访问到nums【0+1】即3,nums【0+2】即1,nums【0+1】,它可以走到nums【0+1+3】,对于nums【0+2】,它可以走到nums【0+2+1】,所以下次的节点我们要选择nums【0+1】即3。
2025-02-24 15:25:40
173
原创 贪心算法:跳跃游戏,用回溯法来做你就慢了!!
这道题我一开始想的是回溯算法,把坐标begin和数组nums作为参数,每一层访问nums[begin],直到begin为nums.length-1则说明走到了最后一格。因为回溯本质就是一个多次、多层for循环的暴力搜寻,所以时间比较长,超时说明这道题肯定有简单解法。我们每次访问一个元素,都更新元素能到达的。
2025-02-24 13:27:36
141
原创 贪心算法:最大子数组和
这题一眼看去,没啥思路,只有两层for来暴力求,但是我们这么思考:我们每次把子数组的累加和记作sum,,如果sum为负数即<0,那么sum+下一个元素就肯定小于下一个元素本身,所以遇到sum为负数的情况,则要开始重新把下一个节点看作新的子数组,放弃之前的子数组(但是如果之前子数组为max,则要保存起来)。
2025-02-22 17:14:43
154
原创 贪心算法:分发饼干
贪心算法的思路:没有套路,每次求局部最优解,那么答案就是全局最优解,不要去证明,靠感觉做题。对于本体,我们每次都让胃口大的小孩吃最大的饼干,那么每次都是最优解。
2025-02-22 15:13:03
188
原创 回溯算法:解数独
这题与普通的回溯算法相比,要注意这几点:1)只要遇到一个满足的,就结束搜寻。(所以我们的函数返回值用布尔,遇到了就向上传递)2)如何判断棋盘的正确性。(判断函数,其实本质就是一个剪枝,如果不正确就把这个点剪掉)
2025-02-21 21:16:40
216
原创 回溯算法:N皇后问题(Java),关键是判断棋盘的合法性!
和组合、排列、分割、子集等问题不一样,N皇后问题在判断的时候,需要一个单独的函数来判断,而不是在for循环里通过简单的一两句话来判断。
2025-02-21 15:30:21
117
原创 回溯算法:全排列2,used数组的两种方法,在一个题里体现。
这道题我们既要做到同一层去重,也要做到层与层之间的元素不能被重复使用,所以对于used数组的两种使用方式我们都要用。
2025-02-20 20:00:30
315
原创 回溯算法:全排列,used数组又派上用场,和子集问题的去重有和不同?
首先这道题是排列问题,这也就代表着同一些元素,用不同的组合顺序,都是不同的答案。假如数组为【1,2,3】,那么for循环遍历到2,下一层的遍历也要从1开始。那么这里面该如何避免出现【2,1,2】等不同层之间重复的情况呢?这里要选出我么的老朋友used数组,在子集问题出现过。但是这里的用法却不一样,子集2这道算法题体现的是同层之间的去重,而这道题是要避免不同层之间的同一个元素被重复使用。所以used的使用方法不一样,具体参考代码里的判断条件。
2025-02-20 19:22:04
283
原创 回溯算法:非递减子序列子集,这题的去重并不是通解!!!!
这道题是有重复元素的,我们需要做到单层去重。可以参考以下链接但是,以往的去重我们都是利用used数组和对输入的数组进行排序才做到的,这道题要求我们求子序列,我们是无法先把输入数组排序的,那该如何做呢?这题可以对每一层的元素都建立一个set集合,如果访问过的元素,就把他放入set。
2025-02-20 19:08:57
212
原创 回溯算法:子集2
该题的重点在于,同一层访问过的元素不能再次访问。所以重点在于:1)同一层,访问到的元素已经访问过,则直接跳过。2)非同一层,访问到的元素已经访问过,不受影响。方法:创建一个used数组来实现。
2025-02-17 21:01:10
163
原创 回溯算法:子集,理解一个关键点就简单
对于普通的回溯问题,我们一般是在到达终止条件才把结果加入结果集,但是对于子集,我们的每一个节点,都是属于一个结果集,终止条件只是表示我们需要返回上一层。所以,这题的关键就是每一个节点,都把其加入到结果集。
2025-02-17 17:28:33
153
原创 回溯算法:复原IP地址,切割类的问题,重点在在循环里判断可行性,而非终止条件里!
这道题目的关键是,我们在当前层,需要判断对应的字符串是否为合格(0-255,且不能以0开头),那这个判断该在哪里做?做完了该如何进行下一步呢?不同于组合问题,这里的判断要在循环里就进行,为什么呢?因为这里的判断,既需要当前层的起始位置,也需要当前层的访问位置,所以在下一层完不成判断。
2025-02-17 15:57:16
236
原创 回溯算法:分割回文串,这题关键在当前层判断
这题的关键点在于:1)我们如何表达子串2)我们需要判断是否是回文子串3)如果当前层的子串不是回文形式,那我们就不能往下深入,而是for循环到下一个。
2025-02-15 20:13:08
207
原创 算法:组合总和,不需要向下去重怎么写?
这道题允许同一个数字出现多次,也就是说,我们在向下探索的时候,可以不用改变宽度。所以我们在向下探索时,不主动改变搜索范围即可(不显示写出),直到有终止条件才会改变搜索的范围。
2025-02-15 17:51:56
226
原创 算法:组合总和2,回溯算法除了向下去重,同一层也存在去重问题!!!
这道题,除了每次向下找新元素时需要进行去重,还需要在同一层进行去重。比如数组【10,1,2,7,6,1,5】,我们先对它排序为【1,1,2,5,6,7,10】,如果target为8,那么如果我们按照正常的回溯(包含向下去重),也会出现两个【1,2,5】,因为在遍历到第二个1的时候,还有一次,所以我们要避开这种情况。如何避免呢?那我们就需要在同一层进行去重操作!需要一个标致来提醒我们,这个数字在之前是否被访问过。我们可以用数组或者哈希表的方式来实现。
2025-02-15 17:33:17
153
原创 算法:电话号码的字母组合
这道题变化就变化在,如何去找递归的下一层。举个例子输入为“345”,那么第一层就是3对应的‘def’,第二层就是4对应的‘ghi’,第三层就是5对应的‘jkl'’。对于终止条件,我们用一个参数count来代表层数,如果层数等于字符串的长度,说明已经到达了底层,可以返回了。对于数字和字符串的映射,我们就用map实现。
2025-02-13 15:41:27
290
原创 回溯算法:组合总和3(含剪枝)
建议先去看看,这里有回溯算法最基础的模板题。那么对于这道题,变化在哪?主要是:1)终止条件,需要既满足个数相等,又满足和相等2)剪枝操作 3)回溯操作那么剪枝操作如何进行:1)访问到当前层,之后的元素个数已经不够了,提前return2)访问到当前层,之后的元素和不够了,提前return3)访问到当前层,和超了,提前return回溯操作:1)既要退出path里的元素 2)统计和也要退一个。
2025-02-13 13:58:03
170
原创 回溯算法:组合(leetcode77)
首先给出回溯法的基本框架for里面的逻辑,也就是‘{}’对应单层递归逻辑,也就是每一层要干什么,for的‘()’对应的是单层递归逻辑里包含的元素范围。这道题,我们的单层递归逻辑,肯定是每次给他放上一个元素,使得咱们的结果去逼近结果,所以假设咱们的一个结果集的一个元元素是path,那么单层逻辑:1)path里加上当前层的访问到的节点2)去下一层找新节点(递归操作)如何表示下一层?for循环里的,开始遍历的初始值+1,因为第一个节点已经在第一步被加入到path了。
2025-02-12 20:26:46
281
原创 算法:把二叉搜索树转化为累加树
我一开始连题目都没读懂是啥意思,但后来结合图才发现,实际就是把比一个节点大的val都累加到这个节点上,那这个就好结合二叉搜索树的性质了。我们知道二叉搜索树的中序遍历:左--中--右是从小到大,那么反过来:右--中--左就是从大到小,所以我们从大到小遍历,用一个变量存储累加值,每次遇到节点就赋值给它就可以完成此题。
2025-02-12 17:01:47
118
原创 算法:将有序数组转化为平衡二叉搜索树
这题我们从单层递归逻辑入手,这里题目要求构造的二叉搜索树是平衡的,所以需要这样的遍历顺序:每次取正中间的元素作为root,然后再对两边的数组进行遍历,遍历返回的结果作为root的左右子树。这样终止条件也相映出来了:当数组的长度为0,说明这个子树已经为null了,直接返回null。当数组长度为1,则直接返回该数组对应构成的节点。递归函数返回值。
2025-02-11 20:44:22
234
原创 算法:修剪二叉搜索树,这题很有挑战。。
还是按照老规矩,从终止条件出发:1)如果访问到null,则说明后面没东西了,返回null2)如果访问到一个节点的val<low,说明它的左边的节点的val都小于low,都可以丢掉,那右边呢?这里右边需要再进去做一次递归操作!3)同理,如果访问到一个节点的val>low也需要最对称的操作单层递归逻辑:对root的左右子树分别进行递归操作返回值:把处理好的root直接返回。
2025-02-11 16:18:16
202
原创 算法:删除平衡二叉树的节点,教你一一破解此题
对于二叉树题目,我一般习惯用递归。那么我们按照常规思路,先从它的终止条件入手:当我们递归走到下面,发现以下情况,则可以终止,向上返回1.遇到null,说明我们没找到想要找的节点2.找到了节点,它的val和key相等,然后我们又要分几种情况:1)这个节点是叶子节点,那咱们直接删除它即可2)这个节点左边还有东西,但右边没有,那么直接返回它左边的节点即可3)这个节点右边还有东西,但左边没有,那么返回它右边的节点即可。
2025-02-11 14:43:49
321
原创 算法:二叉搜索树插入节点
这道题的思路我觉得挺自然的,首先要根据二叉搜索树一直找到需要插入的点(根据大小对比一直找到为null,这也对应了代码的边界条件)。单层递归逻辑:我们在插入了节点后,如何去接到这个节点,那么就是需要它的父亲节点去接返回值:父亲节点接到了下一层的节点,那就接着把自己向上返回即可。所以返回root。
2025-02-10 20:58:46
141
原创 算法:寻找二叉树两个节点的公共祖先,这题又让人意外的地方
首先,我认为要以“向上传递”的方式来作为题目的中心思想,也就是,我们在找到p或q后,要把它向上传到父节点,这样,父节点在作为子节点的时候,就能以传递过来的节点作为参数。这么说太抽象了,直接举个例子把,就拿题目的图举例,假设我们的p是6,q是4,那么我们访问到2的时候,4传递给2,这样,我们在访问节点5的时候,就可以发现左节点的6,右节点是4(节点4传递给2的),此时,就可以把5层层向上传递。也许这么说,还是有点抽象,结合代码及其注释,也许会更明白。
2025-02-10 20:07:02
270
原创 算法:验证二叉树的最小绝对差,知道一个结论就好做了
这里先给出一个结论,二叉搜索树的中序遍历的序列是有序的,知道了这个结论,这道题就不难了。1)首先对二叉搜索树进行中序遍历2)对遍历的结果集,寻找相邻两个元素之间最小的差值。
2025-02-10 15:32:47
304
原创 算法题:验证二叉搜索树,知道一个结论,这个题就方便了
这里直接先抛出一个结论,二叉搜索树的中序遍历是一个有序的序列。那这道题的思路就简单了:1)对二叉树进行中序遍历2)验证遍历结果是不是有序的。
2025-02-10 15:04:58
106
原创 二叉搜索树的搜索,抓住二叉搜索树的性质,代码逻辑很自然就出来
这道算法的思路非常的自然,因为你访问二叉树的顺序已经给你定死了,就是对比值的大小,来决定往左还是往右走。所以思路:1)当访问到的节点值比查找值大,就向左2)当访问到的节点值比查找值小,就向右3)终止条件1:当访问到null了,说明没找到,返回null4)终止条件2:当找到了对应节点,返回对应节点。
2025-02-10 11:53:15
110
原创 合并二叉树,别被吓到,其实就是遍历两颗二叉树
根据题目,其实合并二叉树就是把两棵二叉树同时做相同的遍历操作,然后把遍历到的节点的值合并。所以这里理解了就方便了,然后就是找到递归的终止条件了:当有一个树遍历到null时,说明这里没有节点,此时应该去检查另一棵树的节点,如果两棵树都没有该节点,就可以null。然后单层的递归逻辑,就是以根-左-右的顺序来进行即可。大家可以结合代码来理解。
2025-02-10 11:17:33
159
原创 构造最大二叉树,似曾相识的题目
这种构造二叉树的题,都可以用从根开始向下构建的顺序开始。对于这道题,我们就按照这思路:1)首先是找到根节点,那么怎么找呢??按照题目要求,数组种的最大值对应着根节点2)那么根节点的左右节点如何找到呢?首先我们肯定要把数组分割以下,才能以递归的方式找到左右的子节点以上两点就是本体的主干思想,下面请看第三点完整代码。
2025-02-09 21:34:49
180
原创 由中序和后序遍历,构造二叉树,按照这个思路做很清晰!
这里直接给出本题代码思路,大家当作模板记住,看多了就理解了(很多人会手算,但是一写代码就没法动笔,其实就是练少了,没有把手算的思路映射到代码层面)入参:中序数组,后续数组返回值:构造好的二叉树的root节点。代码构成:1)首先我们要判断数是不是长度为0,如果是则返回null.2)我们需要找到二叉树的根节点位置,那肯定是从后序的最后一个节点,并且new出根节点3)根据这个节点的位置,从中序中得到分割数组的位置,这个位置有助于我们分割中序和后序数组,方便我们之后递归找根节点的左、右子节点。
2025-02-09 20:17:44
288
原创 二叉树路径总和问题,需要理解由底向上的传递
那单层递归逻辑该怎么写呢,这里我们需要知道,我们传入的节点时根节点,但是真正做判断的节点是叶子节点,我们需要把叶子节点的判断,层层向上传达到根节点,所以这里单层递归逻辑应该是:1)对左孩子节点检查,如果true,返向上返回。2)对右孩子节点检查,如果true,返向上返回。那这个路径和的累加过程如何体现呢?也就是我在终止条件里,怎么判断出路径和是不是目标值呢?这题我们从终止条件入手,也就是叶子节点处的判断,只有在访问到叶子节点时,所经过的路径和为目标,才返回true,如果不是,则返回false。
2025-02-09 15:22:17
299
原创 找二叉树的左下角节点:层序遍历如何简化?
这道题基础是二叉树的层次遍历,如果大家不知道,一定要先去了解这道题,我相信很多人第一反应就是层次遍历,这一点大家都没错,可是如何做大尽量简化呢?对于通用的层次遍历,我们的结果集是一个二维的集合,每个元素是每一层的节点,但是这道题需要把每一层所有节点都放入吗?
2025-02-07 21:04:42
137
原创 求二叉树的左叶子节点之和,抓住一个关键点,立刻会做
首先我认为这道题用后续遍历的结构比较好做,这样可以由底向上求每个节点对应的左叶子节点之和。那最关键的是,如何把这个左叶子节点表示出来呢??我们可以发现,如果一个节点,它有左节点,并且这个左节点是一个叶子节点,那么我们就找到了一个左叶子节点。知道了这一点,整个函数的核心已经就被攻破了。我们再来搭一下整个函数的框架:首先递归三部曲:入参:root终止条件:节点为null单层递归逻辑(后续):左:对左节点递归,并且判断这个左节点是不是一个叶子节点。如果是就把其的值加上。右:对右节点递归。
2025-02-07 19:29:11
139
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人