
Leetcode算法题
文章平均质量分 50
丶lemon7
热爱学习,爱加班️
展开
-
买卖股票的最佳时机 II
某一天买入股票,未来任意一天卖出,只能卖了再买,但可以买卖多次,并允许同一天卖出后再买入,求最大利润。先定义两个指针i ,j ,i表示当前股票的价格, j表示下一天股票价格,只要有利润就记录。因为要保证利润最大,只能逢涨就买入,遇跌不买。有利润就买卖,只看眼前。原创 2024-02-28 15:23:03 · 468 阅读 · 0 评论 -
买卖股票的最佳时机
这时发现股票有涨幅,但不一定第 j 天卖出的利润最大,还需观察,先把第j天卖出的利润记录下来,接着 i 不变, j++,题目说了,某一天买入股票,未来任意一天卖出,只卖一次,求最大利润,i 尝试买入,j 尝试卖出。我们能发现一个规律:当遇到涨时,i不变,j++, 遇到跌时,i 变为 j, j++此时到第j天卖出仍有涨,所以i不变,j++,一直找到最大利润。原创 2024-02-26 09:41:36 · 365 阅读 · 0 评论 -
设计推特(Leetcode355)
同样,一个用户可以发送多条文章,用户和文章也是一对多的关系,因为题目有一个方法,获取一个用户发送的近10条文章(其中包括关注者发送的),我们可以用一个链表来存储推文,在用户类中设置一个头节点。这里面有个方法getNewsFeed()获取最新的10篇文章, 包括自己发送的和关注者发送的,其实这就是一个多链表合并问题,按推文时间合并,可以采用大顶堆的方式把自己的推文和关注者的推文加入堆中,然后从堆中弹出一个最近的文章,然后再加入该链表的下一篇推文。推特其实类似于微博,在微博中可以发送文章。原创 2024-02-25 20:54:44 · 1077 阅读 · 0 评论 -
Leetcode535(设计短网址)
题目要求可以将一个长网址变成一个短网址(encode),也可以通过短网址找到原来的长网址,我们可以使用两个hashMap集合来实现。longToShort 和 shortToLong 两个集合。longToShort集合 的key为 长网址, value为生成的短网址, 同时往shortToLong集合中加入key为短网址,value为原来的长网址。上一种方法要考虑生成的短网址冲突问题, 为了简化判断,可以用递增数来实现。原创 2024-02-22 22:33:51 · 570 阅读 · 0 评论 -
Leetcode155(设计最小栈)
当向栈中加入数据时,比如先加入元素 2 , 在A栈中直接存入 2, 同时新加入元素与 B栈的栈顶元素比较,把较小值加入B栈。保证在每次加入元素后,B栈的栈顶是本次的最小元素。其实和第一种方法思路差不多,我们可以把新添加元素和栈里面的最小元素一起加入栈中,这样我们可以少用一个栈的空间。要存储这样的数据我们可以使用一种特殊的数据类型, --> record ,它是JDK16引用的新语法,刚开始, A栈没有数据, B栈先储存一个元素MAX(整数最大值)。当弹出元素时,A栈正常弹出元素,同时B栈也要弹出元素。原创 2024-02-21 20:45:45 · 583 阅读 · 0 评论 -
Leetcode1206(设计跳表)
这段代码根据 curr.next[level].value < val 这个条件,我们最后找到的节点是目标节点的前一个节点,当然目标节点也可能不存在。①:跳表中的元素已经是排好序的(图中从小到大),而链表中的元素对顺序没有要求,可以乱序。②:创建新节点随机高度,高度尽可能小(如果跳表的每个节点都很高,那么查询效率就低了)注意:这里向下找的条件 和 向右找的条件是互斥的,所以不用再写一个向下找的判断逻辑。③:修改新节点的next指针 和 路径节点的next指针。我们先来找一找跳表与单链表的相同点和不同点。原创 2024-02-20 22:36:25 · 553 阅读 · 0 评论 -
LFU缓存(Leetcode460)
这道题可以用两个哈希表来实现,一个hash表(kvMap)用来存储节点,另一个hash表(freqMap)用来存储双向链表,链表的头节点代表最近使用的元素,离头节点越远的节点代表最近最少使用的节点。put方法分为两种情况:如果要添加的key不存在,说明是新元素,放到key为1的位置上,如果key存在,此时是修改操作,改变元素的value值,对应的频次+1,同样放到对应的位置上。这是kvMap: 它的key没有什么特殊含义,value是储存的节点。注意:freqMap 的 key 为节点的使用频次。原创 2024-02-04 22:21:39 · 661 阅读 · 1 评论 -
LRU缓存(Leetcode146)
我们可以用双向链表来储存数据(key-value),当调用put方法添加数据时,可以将数据(key-value)添加到双向链表的队头,队头的元素表示最新使用的元素,越靠近队尾,就是最久未用的元素。题目要求函数get和put要达到O(1)的时间复杂度,可以用 hashMap 来实现,因为要满足。当调用get方法时,若存在此元素,则从双向链表中把该组数据(key-value)提到队头来。的一个效果,还需要配合一个双向链表来共同实现。链表中的节点为一组key-value。原创 2024-01-31 22:38:06 · 966 阅读 · 0 评论 -
最长公共字串和最长公共子序列
我们可以用动态规划的思想,先创建一个二维表格,可以用str1中的每一个字符代表二维表格的每一列(column),用str2中的每一个字符代表二维表格的每一行(row)。当在比对中遇到相同字符时,我们需要知道上一次比对的字符是否也相同,也就是前一行,前一列的元素,如果相同,则需在上一次的基础上 + 1,不同则赋值为0。求两个字符串的最长公共字串,比如有两个字符串,str1 = "itheima" , str2 = "thema",求出这两个字符串最长公共部分的长度。求解过程中缓存子问题的解,避免重复计算。原创 2023-11-29 21:02:38 · 181 阅读 · 1 评论 -
打家劫舍问题
数组的索引表示要偷的房间(例如1号房),数组中存放的每个元素代表偷到第几个房间能得到的最大价值。如果2号房价值加上0号房价值比1号房价值要大,那么应该放弃偷1号房,要偷0号和2号。偷到第几号房表示现在偷的最大价值,可能延用上一次的结果,并不一定代表这间房被偷了。每一行表示已经偷到第几个房子了,比如,只有0号房时,偷0号房,有两块。简单理解:找出递推公式,将当前问题分解成子问题,分阶段进行求解。时,我们可以放弃偷0号房,直接偷1号房,因为这样价值最大。这道题可以用动态规划的方式求解,我们先创建一个数组,原创 2023-12-02 15:09:26 · 63 阅读 · 0 评论 -
最长递增子序列(Leetcode300)
然后我们需要准备两层循环,第一层循环要循环(数组长度 - 1) 次,表示第一个元素不需要往前找其他元素组合,因此不用处理。可以从索引1开始处理,从第二个元素开始需要往前找其他元素组合成最长递增子序列,例如:6可能要和前面的1,2做组合,4可能要和前面的1,3,6做组合。依次类推,需要循环4次。数组需要进行初始化,一开始数组中的每个元素只和自己组合,因此长度都为1。第二层for循环:表示当前元素要和前面的元素比较最长递增子序列的长度,需要更新长度。例如:4可能要和前面的1,3,6组合,最多循环比较更新3次。原创 2023-11-30 21:07:20 · 65 阅读 · 0 评论 -
至少 k 个字符的最长子串
题目要求子串中的每一字符出现次数都不能少于k, k 在参数中给出,举个栗子: 字符串 "aaabb",这时 k = 3,它的最长子串为 "aaa"。同理,在字符串"ababbc"中,c字符只出现了1次,题目要求子串中每一字符出现两次,因此最长子串只能是"ababb"。因为 k = 3,我们需要把原始字符串中字符出现次数小于3的字符剔除掉,其中x出现一次,c出现两次,e出现一次,将来组合子串的时候,谁带上它们谁倒霉~核心思想:统计字符串中每个字符的出现次数,移除那些出现次数 < k 的字符,原创 2023-12-09 20:38:15 · 104 阅读 · 0 评论 -
组合 - Leetcode77
我们可以采用之前全排列的思想,先固定1,然后找有效的组合数(12,13,14),回溯, 再固定2,找到23,24, .... 固定4时,因为后面已经没有其他的数与4组合,因此单独的4为无效组合。如果 n = 4,k = 3,假设现在处理的是数字 1 (还没有把1加入栈里),现在栈中还缺3个元素满,而现在的备用元素是 1,2,3,4。假如 n = 4, k = 2, 表示在 1 ~ 4 中随意找两个数组合,返回所有可能的组合,不能重复。组合有 1 2 ,1 3, 1 4,2 3, 2 4, 3 4。原创 2023-12-12 19:37:28 · 147 阅读 · 0 评论 -
Leetcode167 - 两数之和Ⅱ
用双指针的思想,定义两个指针i,j,i指向数组中的第一个元素,j指向数组中的最后一个元素。把指针i,j所指向的两个元素相加和target比较。蓝色的线代表target,黑色的线分别表示数组中已排好序的元素。i + j 和 j + i 的结果图中都画出来了(看哪根线都一样)..... 重复上述过程,直到找到和为target的两个元素。①:两个指针 i 和 j 分别指向最左侧和最右侧的数字。不难发现,i + j 的结果大于 target,因此。,让i + j的和变小一点。先把i处和j处的元素相加。原创 2023-12-20 19:01:27 · 92 阅读 · 0 评论 -
最长公共前缀(Leetcode14)
一列一列地进行比较,先比较第一列的字符,若都相同,则 i ++ ,继续比较第二列的字符。直至出现不匹配的字符。j表示数组中的每一个字符串, i 表示每个字符串中的第几个字符。情况2:比较某一列时,遇到字符串长度不够,i 之前的字符就是解。情况1:比较某一列时,遇到不同字符, i 之前的字符就是解。情况3:i 循环自然结束,此时第一个字符串就是解。这样比较会出现以下3种情况,需要分开处理。我们可以都用第一个字符串作为返回的模板。我们可以先定义两个变量 i , j,原创 2024-01-20 22:01:48 · 477 阅读 · 0 评论 -
Leetcode39 - 组合之和
假如现在有一个数组candidates = [2, 3, 6, 7],需要组合和为7(target = 7),我们可以先固定2,此时 target = 7 - 2 = 5, 还不够,要继续组合,继续从数组的开始(第一个元素2)进行组合,因为数组中的元素可以被重复选取。再固定2,2, target = 3,固定2,2,2,target = 1,再固定2,2,2,2,此时 target = -1 < 0,不满足条件,要回溯到2,2,2。接着和3,6,7组合(保不齐数组中有个元素1)。图中蓝色的矩形表示有效解。原创 2023-12-13 18:50:01 · 76 阅读 · 0 评论 -
Leetcode15 - 三数之和
这道题可以用之前两数之和的解法。三数之和,我们可以先固定一个数,比如先固定 -4,那么接下来我们要找的两个数之和等于 +4就行了,看看能不能找到解,然后再固定其他的数。固定 -1, 0,1,2(重复的元素不用固定)给定了一个数组,先排好序:nums = [ -4, -1, -1, 0, 1, 2], 题目要求返回。此图中已经固定了 - 4,接下来找剩下两数之和等于target = 4 就可以了。注意:运用之前两数之和的解法需要数组先排好序。其实这道题类似于力扣的40题组合的题目。原创 2023-12-21 11:57:52 · 373 阅读 · 0 评论 -
快速幂 - 分治
介绍快速幂之前我们先来看一道例题。原创 2023-12-05 21:12:43 · 138 阅读 · 0 评论 -
最长回文子串(Leetcode5)
寻找最长回文子串,简单说就是以一个字符为中心点,由中心点向两边扩散,如果两边的字符相等,则继续扩散,直至两端的字符不相等,此时就找到了最长回文子串的左右边界(left,right)。根据数组的遍历顺序,一开始以字符b为中心点,并记录此时回文子串的长度,如果后续找到了更长的回文子串,则替换之前的长度。但这样显然不行,因为b、c不一样,必须找到两个一样的字符作为中心点。注意:以两个字符作为中心点的时候,i不要遍历到数组末尾元素,否则会索引越界。但是在这里我们还遗漏了一种情况,我们只考虑了中心字符为奇数的情况,原创 2024-01-22 21:32:23 · 557 阅读 · 0 评论 -
解数独 - 回溯
③:先在表中找到空方格,然后向空方格填入数字,逐一尝试1~9(检查要填入的数字是否冲突),填入成功后记录填入数字后的冲突,如果1~9都不能填,则回溯到上一次的状态,重新填。我们需要记录表格内每一行是否有冲突,每一行又有9个数字,需要知道这9个数字是否被使用过,被使用过的数字记为true,因此可以创建一个boolean型的二维数组来记录冲突。接着创建九宫格冲突状态:需要找到每个小方格和九宫格的对应关系,i 表示二维表格的行,j 表示二维表格的列,2、一旦1~9 都尝试失败,回溯到上一次状态,换数字填入。原创 2023-12-19 20:59:20 · 90 阅读 · 0 评论 -
平方根整数部分
我们还是同样求99的平方根,可以求 1 到 99之间的中间值,是(1+99)/ 2 = 50,然后算出50的平方, 50 x 50 = 2500,远比99大, 继续缩小范围求中间值,这次是 1 到 49 之间,(1 + 49)/ 2 = 25,25 x 25 = 625 > 99,还是比99大,继续缩小范围,以此类推。因为9的平方是81(9x9=81),比99小,10的平方是100(10x10=100),比99大,因此99的平方根肯定介于9 ~ 10 之间,为 9.?所以,99的平方根整数部分是9。原创 2023-12-06 20:02:31 · 247 阅读 · 0 评论 -
N皇后问题 - 回溯
按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。n皇后问题研究的是如何将n个皇后放置在 n x n 的棋盘上,并且使皇后彼此之间不能互相攻击。原创 2023-12-17 13:36:15 · 170 阅读 · 0 评论 -
全排列(含有重复数字) - 回溯
我们可以先给含有重复数字的序列排序,使数组中的相同元素相邻,这时可以把 第二个 1 看成 1',规定 1 必须排在 1' 之前。1' 排在 1之前的情况不合理,直接跳过。假如要给[1, 1, 3 ] 进行全排列,不能排列重复。原创 2023-12-11 19:35:20 · 473 阅读 · 0 评论 -
找出字符串中第一个匹配项的下标(Leetcode28)
先给出一个字符串pattern,要拿着pattern字符串和原始字符串(origin)比对,若在origin中找到了pattern字符串,则返回pattern字符串在原始字符串origin中的下标。注意:外层循环不必循环origin.length 次,循环origin.length - pattern.length 次即可。可以使用两个循环来依次比对,外层循环表示从原始字符串索引 i 开始和pattern进行比对,先拿着pattern和origin从第一个字符开始依次比对。原创 2024-01-10 21:34:08 · 532 阅读 · 0 评论 -
滑动窗口最大值(力扣239题)
如果把上图中的数字 -4 改为 1,当往队列加入1时,会把前面的-1,-3覆盖掉,此时队列长度小于滑动窗口值,用单调递减队列找到的最大值(数字3) 其实是过期的。我们可以使用单调递减队列来找到滑动窗口中的最大值,每次向单调递减队列加入元素,队列的队头元素就是滑动窗口里面的最大值。这里可以利用索引,当遍历到第 i 个索引时,i - k 处的元素就是过期的元素,应该移除。如果向单调递减队列中加入数字 1,可以直接加入,不会改变队列中递减的要求。当队列中的元素超过滑动窗口的范围( k ),要及时把队头元素移除。原创 2024-01-03 23:22:51 · 506 阅读 · 0 评论 -
盛最多水的容器(力扣11题)
我们可以先固定第一个挡板( i )和最后一个挡板( j ), height[0] = 1, height[8] = 7,看看盛水量。我们发现,固定了两个挡板,当移动高的挡板时,盛水量随着 j 指针的左移在不断减少,必然小于最初的盛水量,因此我们不能移动高挡板。这道题给出了一个数组,数组里的元素可以看成每一个挡板,要找到哪两个挡板之间盛的水最多,返回盛水量的最大值。现在盛水量比较少,要让盛水量尽可能多,假设我们先移动 j 指针。移动较低的挡板,盛水量是有可能增多的。这其实是一个双指针问题。原创 2023-12-30 11:40:34 · 447 阅读 · 0 评论 -
Leetcode40 - 组合总和Ⅱ(回溯)
其实这题的解法和Leetcode39题解法类似,上面给定的集合【10,1,2,7,6,1,5】中,1有两个,我们可以把它们看成之前的1 和 1', 规定1' 只能出现在 1 之后,否则无效。注意:题目中说了每个数字在每个组合中只能使用一次,而且解集不能包含重复的组合。原创 2023-12-13 20:12:13 · 73 阅读 · 0 评论 -
接雨水(Leetcode42)
②再计算高度:注意右边的柱子right不一定比left高,pop的高度不一定为0,我们应该从right和left中选出高度较小的(min),Math.min(right, left), 然后再用(min的高度 - pop的高度)与上面计算的宽相乘就能得出雨水的容量。图中左边表示栈底,当新加入的元素(right)比栈顶大时,先把栈顶元素弹出,被弹出的元素记为pop,此时需要检查pop的左边是否还有元素,若有元素表示存在凹陷,应该计算雨水容量。因为5比2、3、4都要大,要把这三个元素先弹出栈,再加入元素5。原创 2024-01-09 10:09:28 · 521 阅读 · 0 评论 -
全排列-回溯
程序在运行过程中分成了多个阶段。通过某些手段,将数据恢复到之前某一阶段,这就称之为回溯。手段包括: ①方法栈 ②自定义栈比如给数字1, 2, 3进行全排列。我们可以先固定数字1, 对2,3进行排列;然后固定2,对1,3进行排列;最后固定3,对1,2进行排列。在代码实现时,我们需要准备两个数组,一个代表原始数组【1,2,3】,另一个数组,用来表示数字是否已固定(被使用过),已固定用灰色表示,未固定绿色表示。是个boolean变量。原创 2023-12-10 20:43:47 · 102 阅读 · 0 评论 -
最小覆盖子串(Leetcode76)
先定义两个变量i,j,一开始,i 和 j 都指向原始字符串的0索引处,看看此时 i ~ j 范围内的字符串是否满足目标字符串(t),如果不满足,则 j 指针往后移动(j++),i 指针先不动,扩大 i ~ j 的范围,直至i ~ j 范围内的字符串满足目标字符串(t),此时记录i 和 j 的位置。然后 j 指针不动,i++,在满足目标字符串的情况下不断缩小范围,找到最小覆盖子串。2.如果原始串 i ~ j 范围内不满足条件,j++ 扩大范围,直到满足条件 j 停下来。原创 2024-01-25 21:40:47 · 690 阅读 · 0 评论