自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(34)
  • 收藏
  • 关注

原创 LeetCode 179. 最大数(贪心)

题目思路 这道题需要求出能组成的最大数,思路上比较容易想到贪心,进一步思考可以发现只需将数组按照某种规则排序后加起来就是答案,但是这个规则是什么呢?这里需要给Python指定排序的key参数。对于两个待比较的字符串,排序规则为查看两个字符串正反相加后的字符串,把字典序大的组合中排在前面的字符串也排在前面。这种方法可以保证在排序过程中每次形成的都是尽量大的字符串,最后的答案也是能组成的最大字符串。代码class Solution: def largestNumber(self,.

2021-04-12 21:31:31 291

原创 LeetCode 5768. 最小侧跳次数(贪心)

题目思路阅读完题干后可以发现需要侧跳的时机是下一个点有障碍,且障碍处在青蛙当前所在跑道。在做周赛时我是先考虑了特殊情况,即当前青蛙所在点的另外的跑道也有障碍,这种情况下青蛙只有唯一的侧跳选择(因为有两条跑道都被封住了)。而如果青蛙所在点所有跑道都没有障碍,那青蛙当前就有两条跑道可以选择。这时可以用贪心的想法,对于待选的两条跑道,分别查找它们下一个最近障碍所在地点,然后选择其中较大者,即保证青蛙在尽量大的距离内不做侧跳调整。在查找下一个最近障碍所在地点时,我是先保存每个跑道障碍出现的地点,

2021-04-11 19:37:11 309 1

原创 LeetCode 1663. 具有给定数值的最小字符串(贪心)

题目思路这道题要求答案的字典序最小,一个朴素的想法是前面尽量填a,那么那么前面究竟最多可以填入几个a呢?答案是保证在填了a以后,空余的位全部填z加和之后仍然能满足题目要求。所以可以通过循环找到对应位置,这里我是用数学表达式取代了循环。找到要填多少个a以后用k减掉相当数量的a,剩下的数如果小于等于26,则填入对应代表的字母即可。否则在字符串末尾尽量填z,最后剩下的数再用对应的字符填充。代码:class Solution: def getSmallestString(self, .

2021-04-10 12:40:25 292

原创 LeetCode 1540. K 次操作转变字符串(贪心)

题目思路 这道题的特殊之处在与第k次操作正好要将一个字符切换k次,而根据题意,切换一个字符k次和k+26n次是等效的,这里的n可以理解为“轮”。如果两个字符串的比较过程中出现了最小切换次数相同的字符,那么它们肯定有一个要在下一轮中才能操作成功。即有m个最小切换次数为l次的字符的话,那么至少需要m+(l-1)*26次操作才可以。因此本题只需要在遍历比较的过程中找到最大的操作次数,最后和k比较即可。代码class Solution: def canConvertString(s..

2021-04-09 22:51:34 260

原创 LeetCode 402. 移掉K位数字(贪心)

题目思路 这道题题干中描述的是“移除”,也就是剩下的字符依然要保持原有的排列顺序。同时要使得剩下的数字最小,那需要保证小的数尽量排位在前面。综合考虑本题可以使用单调栈的思路,遍历字符串,如果当前遍历到的字符小于栈顶字符,此时弹出栈顶字符可以使得小数尽量排位在前。在遍历过程中要注意考虑K次的限制,当K减为0时,表明已经不能再删除字符,此时要退出循环。同时如果字符中递增的字符数量较多,可能会出现遍历完后K还没减到0的情况,这种情况需要删除字符末尾的k个字符。在解答时直接使用切片返回答案数组中n前n.

2021-04-08 17:37:15 123

原创 LeetCode 738. 单调递增的数字

题目思路这道题目要找到符合条件且小于或等于N 的最大整数,最先想到的思路是贪心。按照题意,如果原本的数字就是递增排列的,则返回原数即可。如果有递减的情况存在,则从左到右找到第一个出现递减的地方,将该位减1,后面的位数均变成9,这样就能保证既小于原数,又能取到最大值。但是要注意一种特殊情况,例如‘332’,这种情况如果直接在第一个2处让2减1的话,则更改后的数字不符合递增的条件。这种情况是在有连续的位相等的情况下出现,因此在找到第一个出现递减的地方后,应该向前遍历,直到找到不相等的地方,将这个地.

2021-04-07 18:33:01 111

原创 LeetCode 1749. 任意子数组和的绝对值的最大值

题目思路这道题我在刚开始做时是想的动态规划的做法。考虑到已有和最大子数组的动态规划解法,本题要求绝对值最大的子数组,因此再维护一个以当前元素结尾的子数组和最小的数组,绝对值最大的数一定在和最大和和最小中产生。后来借鉴了其他大神的解法,这道题可以先求出前缀和数组,然后用其中的最大值和最小值相减即可(因为题目是求绝对值最大,因此不用考虑前缀和中减数和被减数的位置关系)class Solution: def maxAbsoluteSum(self, nums: List[int]) -.

2021-04-07 00:37:39 282

原创 LeetCode 1813. 句子相似性 III

题目思路这道题思路不难想,但是代码实现细节较多。我在做这道题时首先想的是区分长短句,如果短句中包含长句中没有的单词,则结果一定是false(因为短句只能通过增加句子补充到长句,但是不能删除句子)。之后因为题目要求只能在短句中插入一个句子使其变成长句,换句话说长句中出现的短句中没有的单词必须全部是相邻的,否则至少要插入两个以上的句子才可以。因此这里可以遍历长句,同时设定辅助变量并初始化为0,辅助变量用来遍历短句。如果当前遍历时出现了短句中没有的单词,则说明出现了断点,统计断点个数。当断点数量大于.

2021-04-05 13:56:37 187

原创 LeetCode 910.最小差值(贪心,转化)

题目思路这道题虽然能明确想到是贪心思想,但是具体的算法不容易想到。首先为了能直观快速找到经过处理后数组的最大值和最小值,需要对数组进行排序。之后再考虑的时候应该尽量上较小的值变大,较大的值变小(使它们更加接近)。这里的变大变小应该从区间的角度思考,即某一个区间的值全部变大,后面区间的值全部缩小(这里很难给出严谨的证明,但是如果不考虑区间,只考虑原有的最大最小值或类似算法很难考虑到所有情况)。所以需要枚举增大区间和减小区间的临界点(即遍历数组),因为当前数组已经排序,所以处理过后的数组最大值在两.

2021-04-03 12:26:56 354 3

原创 LeetCode 1094. 拼车

题目思路 读完题干后一个自然的思路就是模拟汽车的行驶过程,汽车行驶过程中会顺序经过每个站点,因此现将原数组按乘客上车地点升序排列。之后遍历数组,在遍历过程中每经过一个站点,就需要统计从上一站到该站下车的旅客有多少,先将下车的乘客数补回空座位,然后再判断当前站乘客是否能全部上车。统计下车乘客时有两种方法:一是遍历该站之前的所有站,对于还未处理过的站,判断当前上车地点是否已经过了该站对应的下车地点,这个算法的时间复杂度为O()。代码如下所示:class Solution: def c.

2021-04-02 12:42:02 518 3

原创 LeetCode 1673.找出最具竞争力的子序列(单调栈)

题目思路 这道题的题干是和子序列相关的,并且最后要求出同等长度的子序列中字典序最小的情况。考虑借用栈这种数据结构,栈中储存当前的一个可行解。遍历字符串,如果遇到当前字符比栈顶字符字典序小的情况,就尽量多得从栈中弹出原有元素,最后再将该元素加入。不过这里 有两个细节需要考虑,一是如果当前栈中元素个数还未达到k值,则即使没有元素出栈,当前元素也应该入栈;二是出栈的时候需要考虑剩下元素与栈中还需要填充元素个数的关系,如果剩下的元素个数只够刚好填充栈使栈中元素达到k值的话,那么此时就不能再弹出元素,否.

2021-03-31 21:06:12 460

原创 LeetCode 1664. 生成平衡数组的方案数(前缀和)

题目思路 这道题的数据范围为1e5,因此不能通过暴力方法解题。解答本题的关键在于当删除一个数以后,如何计算剩下的数组中奇数下标项和偶数下标项之和。进一步思考后会发现,当删去一个数以后,该数之后的奇偶性会发生交换。因此可以考虑用前缀和处理出原数组中奇数下标项和偶数下标项的前缀和,之后再遍历数组。对于删除一个确定的项,剩下数组的奇数项之和等于原数组中该项之前的奇数项之和,再加上该项之后的偶数项之和,偶数项之和的计算方式类似。通过这种方式就可以遍历一遍数组中找出最终的答案。在计算原数组的前缀和时有一.

2021-03-30 00:19:47 168

原创 Leetcode 991. 坏了的计算器(贪心,逆向思维)

题目思路 这道题当X>=Y时只能进行递减操作,所以结果为X-Y。X<Y的情况,如果正向思考,即思考如何从X到Y的话思路比较复杂,因为很难描述从X开始每次应该选择哪一种操作。理想状态应该是在接近Y的1/8,1/4,1/2的情况下进行加倍操作,但是从程序角度不好描述。这道题比较好的思路是逆向思考,即思考如何从Y到X,此时对应的Y的操作为加1和除以2。从Y的角度需要尽量除以2,该操作需要在Y为偶数时进行,否则要先加1再进行操作,知道Y<=X,之后只调用+1操作即可。这样对于Y 来说.

2021-03-28 22:47:19 167

原创 LeetCode 1702 修改后的最大二进制字符串(贪心)

题目思路 这道题的切入点在于题面中所给出的第二个操作。子串中所有的“10”可以变成“01”,也就是说当出现1和0交替的情况时,可以通过这种方法将0尽量移动到前面。而当多个0聚集到一起后,就可以使用第1个条件将前方的0都改为1,最后只留下一个0。还要考虑到的是如果从字符串开始位置有连续1出现,则这些1是不用移动的。所以经过这种方法初步处理过后,对应的列表会出现111.....000....11这种情况,之后使用第2条规则将中间的0化为只有一个0,这就是最终答案。在使用算法之前需要特判一下原字符..

2021-03-26 19:52:00 276

原创 LeetCode 1053. 交换一次的先前排列(贪心法)

题目思路 这道题的要求初看还是比较复杂的:既要字典序小于原来的序列,又要在小于的字典序中求出最大值。按照题目的要求,应该尽量交换排在后面的元素,因为交换越到后面的元素所产生的的字典序“增量”越小,也就更接近与题目的要求。而题目中需要交换的地方即出现了逆序的地方(即i<j且A[i]>A[j]),如果数组中有这样的逆序则证明可以通过交换元素使字典序减小,从而符合题目要求。但是最终的答案并不是直接交换相邻的元素,而是在发现一个相邻的逆序对后,记录当前较大的值并继续向后搜索,在这个遍历过程.

2021-03-25 23:40:54 337

原创 LeetCode 1705. 吃苹果的最大数目(贪心,最小堆)

题目思路这道题的总体思路为贪心,为了尽可能的“节省”现存的苹果,需要优先吃掉最早可能坏掉的,即优先吃掉坏掉天数最小的苹果,因此需要有一个数据结构能够存储当前坏掉天数最小的苹果。可以使用Python的heap库中的相关方法,将列表变成最小堆。堆中的元素为列表或元祖,其中过期的天数是第一位元素,苹果数量是第二位元素。循环的条件为列表不为空或者天数在题干所给天数范围内,在每次循环时要先弹出已经过期的栈顶元素,然后如果天数在题干所给天数范围内的话且对应的苹果数量不为0则将对应的元素入栈。当前堆不为空的.

2021-03-24 23:39:49 361

原创 LeetCode 870. 优势洗牌(贪心,二分)

题目思路 这道题的解题思路主要为贪心,其思想和田忌赛马类似。题目要求对于同一个索引位置,A[i]>B[i]的索引数目。为了让“资源”利用率最大化,对于B位置某个索引处的元素,对应调出的A数组中的元素应该是刚刚好大于它,也就是A数组中大于该元素的第一个数。如果不存在这样的数(或者有合适的数但之前已被占用)则将当前A数组中可用的最小值分给它,减少资源的损失。为了更快查找到该元素,需要先对A数组进行排序。之后遍历B数组。对于B数组中的而每个元素,在A数组中二分查找第一个大于当前元素的数并加入答.

2021-03-23 22:28:16 260

原创 LeetCode 316. 去除重复字母(单调栈)

题目思路 这道题要求不能打乱字符之间的相对位置,因此直接用朴素的贪心方法不可以行。为了保证这一条件,需要用栈来模拟这一算法过程。在遍历字符串过程中,添加当前字符串入栈的前提是它在栈中没有出现过。如果遇到当前字符比栈顶字符字典序小则需要弹栈,不过这里有一个前提,也就是当前栈顶字符在剩下的子串中会再出现,否则不能弹出。如果当前栈顶字符比当前字符字典序小,则直接将当前字符入栈。在模拟过程中需要用一个数组记录当前每个字符还剩的个数以及字符是否在栈中出现过。代码class Solu...

2021-03-22 21:05:52 143

原创 LeetCode 881. 救生艇(贪心法)

题目思路 这是一道经典的贪心问题。可以从体重小的人的方面来考虑,当一艘船承载一个体重较小的人后,最节省的方案就是再载一个体重尽量大的人。因为如果不这样的话,这个体重较大的人在后面可能需要一艘单独的船来承载,最终的答案也会变大,这种思路实际上是以尽量小的代价抵消尽量大的代价。具体实现时先对列表进行排序,之后采用类似双指针的方法,令两个指针分别指向第一个元素和最后一个元素。如果当前两个指针指向的人可以做一艘船,则答案加一,左指针右移,右指针左移。否则说明右指针指向的元素只能单独放到一条船里。依次..

2021-03-21 17:39:37 308

原创 LeetCode 1567. 乘积为正数的最长子数组长度(动态规划)

题目思路 这道题给出的数组长度为10的5次方,所以普通的暴力遍历方法肯定不行。本题最直观方法为动态规划法,定义两个数组p和ne,其中p[i]代表以i结尾的最长正数积子串的长度,ne[i]代表以i结尾的最长负数积子串的长度。通过第一个数给出初始值,之后遍历整个数组:如果当前的数为正数,则对之前的运算结果符号无影响。对于p数组可直接在前一位的基础上加1,而对于ne数组,要先判断前项是否为0,如果为0则当前项仍然为0(因为乘积仍然为0),否则才在前项的基础上加1。如果当前数为负数,则将情况情况做翻转.

2021-03-20 22:30:21 296

原创 LeetCode 1775. 通过最少操作次数使数组的和相等(贪心法)

题目 思路 首先要考虑返回-1的情况:对于长度为n的数组,其数组所有数之和的取值范围为[n,6n]。设另一个数组的长度为x,则不可能的情况为6x<n或者6n<x。 接下来考虑一般情况的解法。由于题目要求修改次数最少,因此考虑贪心思路的话,一般会想到对于和小的那个数组来说,尽量增长小的数(因为小的数增长有较大的空间,对和的贡献较大)。同理,对于和较大的数组,则尽量减小大的数,注意对于和大的数组减小元素可以认为是增加和小的数组的元素,因此可以对两个数组进行统一的统计。具体做法...

2021-03-18 23:26:45 555 1

原创 LeetCode 1578.避免重复字母的最小删除成本(贪心法)

题目思路 这道题如果能将问题转化后不难想到贪心的思路。题目所要求的是任意相邻另个字母不相邻,换句话说也就是如果原字符串中如果当前有相连且相同的字母,则要将这些相连的字母删除到只剩一个(如果全部删除则肯定不是最小值,且无法保证前后相接的字母满足题意)。而此时只需考虑:对于每一处只包含n(n>1)个相同字母的子串,从中删除所需代价前n-1小的字母,这样可以保证每一处的成本均是最小值,从而最后的答案也是最小值。而这一过程可以通过一遍遍历来做到。代码 class Solu...

2021-03-16 21:19:03 258

原创 Leetcode 1129. 颜色交替的最短路径(BFS)

题目思路 这道题在搜索相关题目里应该算hard难度的题目了。本题的基本方法比较直接,求最短路径最先想到广度优先搜索(BFS)。首先题目只要求是蓝红交替即可,并没有指定哪个颜色做开头,因此需要分两种情况分别进行bfs,最后对于同一个点,选择两种方法中有数据且较小的数值作为答案。本题的最重要注意点如下: 题目明确说明了该有向图存在自环和平行边,也就是说在搜索的过程中可以经过同一个点两次来达到调整的目的。因此不同于大多数搜索类题目,这道题中同一个节点在搜索过程中最多允许经过两次。...

2021-03-15 22:41:30 285

原创 Leetcode 1781. 所有子字符串美丽值之和

题目思路 这道题的思路并不复杂,直接“遍历”所有子串,求出每个子串的美丽值之和。但是我在做的时候踩了两个坑: 1.不能真的去遍历所有子串。正确的做法是进行二重循环,并在每次外层循环开始时设立一个字典变量存储每个子串所包含的每个字母的个数。当内层循环加1时,只用将内层循环当前指向的字母数量加1即可,这样避免了对于每个子串都重新统计其所包含的各个字母数量。 2.在统计出现次数最少的字母时需要注意,不能按照传统方法,直接设置变量然后遍历一次寻找最小值,因为有可能...

2021-03-13 23:25:48 348

原创 LeetCode 216. 组合总和 III(回溯法)

题目:思路 这道题需要找出所有组合,因此需要使用暴力搜索的方法。而每个答案中数字的个数一定,因此可以使用回溯法。这里我使用的python语言可以直接进行列表的“加减”运算,所以在递归的函数中不用指定搜索过程中存储答案的列表变量,而是直接将当前存储答案的列表做加法运算,作为下一个搜索函数的参数。而为了保证不重复,在搜索完当前方案的最后一个数后,将列表中的数字排序并转换成字符串,使用一个全局map字典来判重。代码class Solution: def combinati...

2021-03-11 23:11:27 154

原创 Leetcode 131. 分割回文串(回溯法)

题目 思路 这道题感觉应该能算上Hard难度的题目了。因为题目要求是求出所有可能的分割方案,因此一般考虑暴搜。根据题意,每种方案需要切分完的每个子串都是回文串,所以在搜索时后面,相应结果应该建立在前面已分割出符合要求的回文串的基础上,如果后面的分割情况无法满足题意,需要推倒之前的搜索结果重来,这是具有明显回溯性质的一种情形。 本题的难点在于如何用代码实现这个搜索过程。由于结果相当于二维列表,所以在一次搜索中直接向下传的应该就是列表,在一种方案搜索完后将这次搜索到的所有结果加入到结果...

2021-03-08 23:55:38 73

原创 Leetcode1775. 地图中的最高点

题目 思路 本题是多源bfs的一道典型题目。根据题目描述可以将所有水域作为bfs的起始搜索点,向外拓展填入每个陆地的高度数值。由于题目要求的是最大高度,即每一步要尽量拔高陆地的高度,因此在搜索过程中对于搜索到的符合条件的陆地区域应该在原有高度的基础上加1。这种思路的正确性可以用反证的思想证明,假如当前陆地位置的最大高度不是相邻位置高度加1,而是从远处水域搜索过来的一个更高的高度,则对于其当前相邻区域无法满足题意要求的高度相差之多为1的要求,因此证明这种思路是正确的。在搜索过程中可以设置一...

2021-03-07 22:58:14 276

原创 Leetcode.1718 构建字典序最大的可行序列

题目描述: 思路: 这道题目乍看之下没有特别适用的算法,于是尝试用深度优先的方法直接暴力搜索。根据题干描述,最后生成序列的长度为2n-1。为了满足第三个条件,在搜索过程中如果在当前位置(假设对应数字为i)填入除1以外的数字(假设为j),则可以在对应i+j位置同时填入j,这样最后得到的序列是满足第3个条件的。而为了满足字典序最大的条件,搜索数字时需要从n向2,从大到小搜索,这样得到的第一个序列就是题目所求序列。以上为基本思路。 在代码实现时,我踩过的坑主要有2个: 1.代码...

2021-02-28 23:01:07 373

原创 LeetCode 978 最长湍流子数组

题目描述 思路 本题的做法为动态规划,思路和最长上升子序列类似。按照题目给出的湍流数组的定义,湍流数组是形如“大小大小......”或者“小大小大.....”类型的数组,因此这里需要设置两个dp数组(或者两个变量)来分别存储两种类型的可行解,两个数组的dp[0]=1,在之后的过程中交叉增长。假设dp1表示第一种类型的数组,dp2表示第二种类型的数组,则如果当前元素大于前一个元素,则是在“小大”类型的数组(dp2)后增加1,而dp1类型的数组中断,这里设置为1,反之亦然。当前后两个数相等时..

2021-02-19 22:51:25 66

原创 Leetcode 1711 大餐计数

题目 思路本题的思路是从提示的数据范围往回推的,由数据范围可知一顿大餐的美味程度最大为2的21次方(2*2的20次方),也就是说能够选出的所有大餐的组合的可能值只能在0,2^1,2^2...2^21次方之间,所以可以用枚举可能的大餐美味值的方法来确定答案。具体做法是先遍历数组,统计每个数值出现的次数(这里我用字典保存)。之后再次遍历数组,对于数组的每个元素再枚举2的0到21次方,用字典查找数组中存在的可以组合成2的次幂的数的个数,累加即可。注意为了避免重复计数,在每次计数之前需要把当前遍..

2021-02-09 22:51:08 305

原创 LeetCode 每日一题 :665. 非递减数列

LeetCode 每日一题 :665. 非递减数列本题题面如下所示:思路: 这道题目我一开始思考时想的比较简单,只是想到题目要求只能修改一处,所以整个序列中a[i]>a[i-1]的情况只能出现一次,因此直接遍历序列即可。提交错误后才发现这个要求并不是满足题目的充要条件,例如对于序列[3,4,1,2],它虽然满足上述条件,却不满足题意。 后来经过仔细思考,考察时因为要确定当出现逆序情况时应该,修改哪个数据,所以仅仅考察相邻的两个元素是无法得出结论的。在这道题目中假设目前出现...

2021-02-07 20:56:37 97

转载 背包问题

动态规划初步动态规划算法通常基于一个递推公式及一个或多个初始状态。 当前子问题的解将由上一次子问题的解推出。使用动态规划来解题只需要多项式时间复杂度, 因此它比回溯法、暴力法等要快许多。以背包问题为例01背包问题有n个重量和价值分别为wi和vi的物品,从这些物品中挑选出总价值不超过W的物品,求这些方案中价值最大的一种。这类问题最易想到的就是朴素递归进行穷竭搜索,但是递归过程无论是算法复杂度还...

2019-04-06 17:17:36 140

转载 贪心思想

贪心思想贪心思想,顾名思义是一种总是选择当前最优的,以期望达到整体最优的方法贪心法一般用于求解最优化问题。采用贪心法求最优化问题的算法,一般都包含一系列步骤,每一步都有一组选择,每次都选择当前最优的选择,希望通过局部最优的选择达到全局最优的选择。贪心法不一定总能产生最优解,可能产生近似解甚至完全不正确的答案,故想使用贪心法,最好是能够能够符合贪心法产生优化解的条件。它的做法大致可以分为以下三步:...

2019-04-06 12:14:09 1923

转载 二分法

二分法二分法是一种很常见的算法,它的具体应用可以分为两大类:二分查找算法、二分排序算法一、二分查找算法二分查找就是将查找的键和子数组的中间键作比较,如果被查找的键小于中间键,就在左子数组继续查找;如果大于中间键,就在右子数组中查找,否则中间键就是要找的元素。用函数可以表示为`` int left = 0,right = len-1,mid; while(left &l...

2019-04-05 20:53:39 1100

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除