LeetCode刷题
文章平均质量分 59
关于LeetCode刷题总结
遮半面涟漪
以非神之身上达天意, 以凡人之躯比肩神明。
展开
-
牛客-NC95-数组中的最长连续子序列
NC95. 数组中的最长连续子序列(medium)方法一:排序方法一:排序写在前面:这道题是剑指Offer II 119. 最长连续序列,也是LeetCode 128. 最长连续序列,字节一二面也考了这道题。思路:被这道题唬住了,其实暴力也能解,思路是排序+计数。循环遍历数组,分为以下情况:当前值和前一个值相等,则跳过本次循环。当前值和前一个值刚好符合连续,即长度差为1,则计数加一。否则,让计数为1(重新开始)。更新最长的长度。可以写出以下代码:public int MLS (in原创 2021-08-03 22:53:22 · 485 阅读 · 0 评论 -
牛客-NC50-链表中的节点每k个一组翻转
NC50. 链表中的节点每k个一组翻转(medium)方法一:指针法方法一:指针法写在前面:这道题考察分段链表的反转问题,个人认为比较难的在于如何使用指针将翻转部分,待翻转部分连接起来,链表题就是这样,需要的指针一多,脑袋就有点发晕了。尽管反转单链表已经写得滚瓜烂熟,但这道题的细节太多了,在LeetCode上这是道hard题目,链接,自己只能参考比较优质的题解,图解k个一组翻转链表。思路:翻转的范围,只能通过k次循环来确定。初始化两个指针pre和end,pre表示待翻转链表的前驱节点,end代原创 2021-07-28 15:31:17 · 252 阅读 · 0 评论 -
牛客-NC70-单链表的排序
NC70. 单链表的排序(easy)方法一:归并排序(递归)方法一:归并排序(递归)思路:这道题考察链表排序问题,朴素解法(暴力解)是直接遍历存值再遍历修改值;但更容易打动面试官的可能是归并排序了吧。我们分两步完成该题,首先是分割,怎么分?需要使用快慢指针去寻找链表的中点,然后以中点为分割点,将链表分为左链表和右链表。再递归进行分割,当head == null || head.next == null达到递归终止条件。如下图的递归终止图,ps:图片来自于K神。举个例子:left = 3, righ原创 2021-07-22 15:23:21 · 335 阅读 · 1 评论 -
牛客-NC37-合并区间
NC37. 合并区间(medium)方法一:排序+指针方法一:排序+指针思路:这道题考察区间合并,我们需要对输入进行预处理,即根据元素左区间进行升序排序,这样保证后续合并的区间是有序的。其次,是通过指针来寻找目标区间的右端点,具体来说,针对一个区间 [x,y],我们将x作为目标区间的left,然后,我们移动指针去寻找第一个大于y的点,并将该点作为目标区间的right。自此,我们可以实现多个区间的合并,再继续往后移动,根据上诉规则进行目标区间的寻找。可以写出以下代码:/** * Definition转载 2021-07-21 09:58:53 · 621 阅读 · 0 评论 -
牛客-NC92-最长公共子序列II
NC92. 最长公共子序列||(medium)方法一:动态规划法方法一:动态规划法思路:这道题分两部分进行,首先是使用动态规划法求解LCS的长度,再逆序构建LCS。先说第一部分:定义一个二维dp数组 dp[i][j]:s1[i-1]和s2[j-1]为止的最长公共子序列的长度。dp[0][0] = 0dp[i][0] = 0dp[0][j] = 0dp[i][j] = dp[i - 1][j - 1] + 1, s1[i-1] == s2[j-1] dp[i][j] = max(dp[i][j原创 2021-07-19 13:41:24 · 329 阅读 · 0 评论 -
牛客-HJ61-放苹果
HJ61. 放苹果(easy???)方法一:递归法方法二:动态规划法方法一:递归法思路:设f(m,n)为m个苹果,n个盘子的放苹果方式数目,则先对n进行讨论:n>m:此时苹果少,盘子多,那肯定会有n-m个盘子永远空着,去掉它们对放苹果的放法没有影响,此时,f(m,n) = f(m,m)。n<=m:此时苹果多,盘子少,做以下考虑:有盘子为空,此时,f(m,n) = f(m,n-1)。假设所有盘子都装有苹果,则每个盘子上至少有一个苹果,此时,可以从每个盘中拿掉一个苹果,并不会影响最原创 2021-07-17 17:49:12 · 961 阅读 · 1 评论 -
牛客-NC97-字符串出现次数的TopK问题
NC97. 字符串出现次数的TopK问题(medium)方法一:HashMap+Collections.sort()方法一:HashMap+Collections.sort()思路:比较直接的做法是:将字符串数组遍历,并将元素放到HashMap中统计出现频率,接着最核心的来了–排序–需要调用Collections工具类来进行定制排序,即先比较值是否相同,相同按键升序进行比较,不相同按值降序比较,最后再取值即可,可以写出以下代码:import java.util.*;public class原创 2021-07-15 10:54:33 · 289 阅读 · 0 评论 -
牛客-NC52-括号序列
NC52. 括号序列(easy)方法一:栈法方法一:栈法思路:用栈可能是解决括号问题最直接的方法了,我们先定义一个HashMap用于存放括号之间的关系,即')'-->'('、'}'-->'{'、']'-->'[',为什么是反着的?这其实和我们常规思维相违背,我们做这样的考虑:当遇到左边括号时,我们一股脑的入栈即可,但一旦遇到右边括号,弹出栈顶元素,我们就要开始做判断了,即该栈顶元素是否与以当前字符数组元素为key所对应的value相等,相等那就继续遍历,否则,说明括号不匹配。当然,也原创 2021-07-13 15:59:13 · 756 阅读 · 0 评论 -
单调栈入门
单调栈入门简介LC题库栈的转化最小/大栈验证栈序列栈排序单调栈简介受启发与ikaruga)的题解,自己复习单调栈。单调栈分为单调递增栈和单调递减栈:单调递增栈即栈内元素保持单调递增的栈单调递减栈即栈内元素保持单调递减的栈操作规则(以单调递增栈为例):如果新的元素比栈顶元素大,就入栈如果新的元素较小,那就一直把栈内元素弹出来,直到栈顶比新元素小加入这样一个规则之后,会有什么效果:栈内的元素是递增的当元素出栈时,说明这个新元素是出栈元素向后找第一个比其小的元素举个例子,配合下原创 2021-07-13 15:41:55 · 98 阅读 · 0 评论 -
牛客-NC128-接雨水
NC128. 接雨水(hard)方法一:暴力法方法二:动态规划法方法三:单调栈法方法四:双指针法(最优解)方法一:暴力法思路:对于数组每一个元素,我们需要找到它左边的最高柱子以及它右边的最高柱子,而盛水的多少取决于左右柱子的较小值减去当前元素柱子高度。看代码:import java.util.*;public class Solution { /** * max water * @param arr int整型一维数组 the array * @retur原创 2021-07-13 10:24:32 · 344 阅读 · 2 评论 -
牛客-JZ40-数组中只出现一次的两个数字
JZ156. 数组中只出现一次的数(其它数出现k次)(easy)方法一:位运算法方法一:位运算法思路:出现k次我们不能再使用之前的异或方法进行解决,但仍可以利用位运算的思想去做。因为出现k(奇数)次的数字每个位(0或者1)也是出现k(奇数)次,因此可以每一位的和能够被k整除(对k取余为0)。所以如果把每个数的二进制表示的每一位加起来,对于每一位的和,如果能被k整除,那对应那个只出现一次的数字的那一位就是0,否则对应的那一位是1。我们需要用一个长度为32(int型二进制表示最多为32位,4字节)的数组b原创 2021-07-11 19:32:37 · 166 阅读 · 0 评论 -
牛客-NC156-数组中只出现一次的数(其它数出现k次)
NC156. 数组中只出现一次的数(其它数出现k次)(easy)方法一:HashMap法方法二:位运算法方法一:HashMap法思路:这个解法是暴力解,直接统计每个数字出现的次数,再遍历返回出现一次的那个数即可。于是,可以写出以下代码:import java.util.*;public class Solution { /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * * * @param arr int原创 2021-07-11 17:55:10 · 366 阅读 · 0 评论 -
牛客-NC59-矩阵的最小路径和
NC59. 矩阵的最小路径和(medium)方法一:动态规划法方法一:动态规划法思路:入门级动态规划,大家可以先看求路径这道题,思想非常接近,注意边界条件和状态转移方程。前者主要是对0行和0列数据的处理,全初始化为累加路径和;后者状态转移方程为dp[i][j]=dp[i-1][j]+dp[i][j-1];于是,可以写出以下代码:import java.util.*;public class Solution { /** * * @param matrix int整原创 2021-07-11 16:25:10 · 297 阅读 · 0 评论 -
牛客-NC34-求路径
NC34. 求路径(easy)方法一:动态规划法方法一:动态规划法思路:入门级动态规划,注意边界条件和状态转移方程。前者主要是对0行和0列数据的处理,全初始化为1;后者状态转移方程为dp[i][j]=dp[i-1][j]+dp[i][j-1];于是,可以写出以下代码:import java.util.*;public class Solution { /** * * @param m int整型 * @param n int整型 * @re原创 2021-07-11 16:11:38 · 191 阅读 · 0 评论 -
牛客-NC143-矩阵乘法
NC143. 矩阵乘法(medium)方法一:模拟法方法一:模拟法思路:可以直接模拟得到答案,需要注意的是:(1)a数组的列数应该和b数组的行数相同才能进行矩阵相乘;(2)新产生的二维数组应该是a数组的行与b数组的列对应的元素相乘得到的。于是,可以写出以下代码:import java.util.*;public class Solution { /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * * @param a原创 2021-07-11 15:39:38 · 190 阅读 · 0 评论 -
牛客-NC1-大数加法
NC1. 大数加法(medium)方法一:模拟进位法方法一:模拟进位法思路:上一题两个链表生成相加链表,我写的三个ArrayList发挥作用了哈(思路很像),但这里可千万别把每一个位置计算得到的值放到ArrayList中,会超时的,样例中有特别特别大的数。那只能另辟蹊径,用StringBuffer直接存储每一位计算得到的值,将int变成character进行存储,从而巧妙地避免了大数越界的问题。于是,我们直接上代码:import java.util.*;public class Solutio原创 2021-07-10 10:19:55 · 314 阅读 · 0 评论 -
牛客-NC40-两个链表生成相加链表
NC40. 两个链表生成相加链表(medium)方法一:链表反转求和法方法一:链表反转求和法思路:先将这两个链表进行反转,再逐一遍历求和,注意进位,最后将新链表反转即可得到答案。import java.util.*;/* * public class ListNode { * int val; * ListNode next = null; * } */public class Solution { /** * * @param head1 L原创 2021-07-10 10:05:03 · 209 阅读 · 0 评论 -
牛客-NC8-二叉树根节点到叶子节点和为指定值的路径
NC8. 二叉树根节点到叶子节点和为指定值的路径(medium)方法一:DFS法方法一:DFS法思路:前序遍历的增强版,要找出根到叶节点的节点值之和等于sum的路径,所以dfs方法需要带一些标记数据,这里包括包含当前节点时的cur_sum和将当前节点纳入考虑的select列表。(注意这里有个Java常问的知识点:深浅拷贝,我被这个东西坑了,一直得不到正确的答案,这里必须对select列表进行深拷贝,因为浅拷贝生成的列表会指向之前的列表,后续对该列表的改变都会映射到之前的列表中导致最终达到目标叶子节点会原创 2021-07-10 09:53:19 · 185 阅读 · 0 评论 -
牛客-NC137-表达式求值
NC137. 表达式求值(medium)方法一:双栈法(表达式计算的通用解法)方法一:双栈法(表达式计算的通用解法)思路:这里借鉴了三叶大佬的题解,自己在这写一遍加深印象。对于任何表达式而言,我们可以使用两个栈nums和ops:nums:存放所有的数字ops:存放所有的数字之外的操作然后从前往后遍历,对遍历的字符分情况讨论:空格:跳过(:直接加入ops中,等待与之匹配的)):使用现有的nums和ops进行计算,直到遇到左边最近的一个左括号为止,计算结果放到nums中数字:从当前位置开原创 2021-07-08 10:46:05 · 654 阅读 · 0 评论 -
牛客-NC17-最长回文子串
NC17. 最长回文子串(medium)方法一:中心扩散法方法一:中心扩散法思路:这里借鉴了weiwei大佬的题解,自己在这写一遍加深印象。首先, 中心扩散法的基本思想是:遍历每一个下标,以这个下标为中心,利用 回文串中心对称的特点,往两边扩散,看最多能扩散多远。枚举中心位置时间复杂度为O(N) ,从中心位置扩散得到回文子串的时间复杂度为O(N),因此,总的时间复杂度为O(N2)。值得注意的是,回文串在长度为奇数和偶数的时候,中心位置是不一样的,具体来说:奇数回文串的中心是一个具体的字符,例原创 2021-07-07 18:18:45 · 635 阅读 · 0 评论 -
牛客-NC141-判断回文
NC141. 判断回文(easy)方法一:双指针法方法一:双指针法思路:使用两个指针left和right,left从左往右遍历,right从后往前遍历,遇到相同字符就将left向后移动,同时right向前移动。不相等时,直接返回,不需要再遍历(因为此时已经不再是回文字符了)。当退出while循环时,说明整个字符就是回文字符。于是,可以写出以下代码:import java.util.*;public class Solution { /** * 代码中的类名、方法名、参数名已经原创 2021-07-07 17:25:01 · 128 阅读 · 0 评论 -
牛客-NC19-子数组的最大累加和问题
NC19. 子数组的最大累加和问题(easy)方法一:直接遍历法(最优解)方法一:直接遍历法(最优解)思路:这里注意题目对时间、空间复杂度的要求,所以我们不能使用动态规划来写(虽然后面提交了也没有超时)。我们首先默认数组中的第0个元素是最大的,然后从下标1开始,遵循以下规则:(1)保证每个位置的值至少比原始的大;(2)每次遍历都更新ret,用于保存当前最大的累加和。于是,可以写出以下代码:import java.util.*;public class Solution { /**原创 2021-07-06 11:22:59 · 151 阅读 · 0 评论 -
牛客-NC88-寻找第K大
NC88. 寻找第K大(medium)方法一:栈法方法一:栈法思路:同牛客-NC119-最小的K个数,求第K大等价于在小根堆中求第N-K+1小,所有改变遍历次数即可:import java.util.*;public class Solution { public int findKth(int[] a, int n, int K) { // write code here // 特判 int ret = 0; if (n原创 2021-07-05 21:12:18 · 130 阅读 · 0 评论 -
牛客-NC45-实现二叉树先序,中序和后序遍历
NC45. 实现二叉树先序,中序和后序遍历(medium)方法一:递归法方法二:迭代法方法一:递归法思路:三种遍历方法最常用得到救赎递归法,写法非常对称,只需要调整当前层的添加顺序即可,于是,我们可以写出以下代码:import java.util.*;/* * public class TreeNode { * int val = 0; * TreeNode left = null; * TreeNode right = null; * } */public clas原创 2021-07-05 20:28:15 · 179 阅读 · 0 评论 -
牛客-NC22-合并两个有序的数组
NC22. 合并两个有序的数组(easy)方法一:直接合并排序法方法二:双指针法方法三:逆向双指针法(最优解)方法一:直接合并排序法思路:这个思路很直接,m是A数组中初始的元素个数,n是B数组中初始的元素个数。且A数组的长度是m+n,因此,我们可以直接通过for将B数组中的元素放到A数组中,由于最终结果需要一个有序的升序数组,我们还需要对新的A数组进行排序,得到最终的答案。于是,我们可以写出以下代码:import java.util.Arrays;public class Solution {原创 2021-07-05 16:17:58 · 297 阅读 · 0 评论 -
牛客-NC119-最小的K个数
NC119. 最小的K个数(medium)方法一:PriorityQueue(优先队列)方法一:PriorityQueue(优先队列)思路:这里先简单介绍PrioriryQueue,它是Queue接口的一个队列实现类,即优先队列,但它的排序不是典型的我们熟知的队列式的FIFO(先进先出)方式。具体来说,分为两种排序:一种是自然排序,即实现Comparable接口的compareTo方法,默认是按照加入元素的大小从小到大排序。另一种是定制排序,就是new对象后面的Comparator对象,重写Compa原创 2021-07-02 13:09:05 · 197 阅读 · 0 评论 -
牛客-NC41-最长无重复子数组
NC41. 最长无重复子数组(medium)方法一:HashSet+滑动窗口方法二:HashSet+滑动窗口(优化)方法一:HashSet+滑动窗口思路:一道滑动窗口题(纯暴力是会超时的,注意看上图的备注信息。),其实很好理解:我们要找最长且无重复的子数组,无重复需要使用HashSet进行去重。要找到最长的,可以使用滑窗的思想去动态地改变长度。有以下情况(1)没有重复数组元素时,right指针一直往右移动,同时更新maxLen和window表。(2)当出现重复数组元素时,我们需要移除left指针所对原创 2021-07-01 14:48:11 · 542 阅读 · 0 评论 -
牛客-NC68-跳台阶
NC68. 跳台阶(easy)方法一:动态规划方法一:动态规划思路:最经典的动态规划题,动态规划最重要的就是状态转移方程,具体到这题考虑如下:爬到第 x 级台阶的方案数是爬到第 x−1 级台阶的方案数和爬到第 x−2 级台阶的方案数的和。这就是状态转移方程,再考虑边界条件,也就是初始条件,从第 0 级爬到第 0 级我们可以看作只有一种方案,即 f(0) = 1;从第 0 级到第 1 级也只有一种方案,即爬一级,f(1)=1。于是可以写出如下代码:public class Solution {原创 2021-07-01 09:42:12 · 425 阅读 · 0 评论 -
牛客-NC15-求二叉树的层序遍历
NC15. 求二叉树的层序遍历(medium)方法一:广度优先遍历(自己写的)方法二:广度优先遍历(LeetCode最优解)方法一:广度优先遍历(自己写的)思路:使用一个队列nodes来存放当前层遍历的节点,将根节点放到该队列进行while循环。while中要做两件事:(1)首先是将当前层的值存放到新定义的cur中,用于返回。(2)遍历当前层的节点,并判断当前节点的左子树和右子树,将这层所有节点的子节点放到nxt_level列表中,用于下一层的遍历。将nxt_level存放到nodes进行下一层的w原创 2021-06-30 20:55:55 · 144 阅读 · 0 评论 -
牛客-NC105-二分查找-II
NC105. 二分查找-II(medium)方法一:递归二分(自己写的)方法二:纯二分方法一:递归二分(自己写的)思路:题目已经给出解题思路:二分查找,但这里需要注意限制条件:首次出现的位置,不可避免地,我们需要递归去二分查找target。当找到时,需要考虑在当前mid的左边可能还有更小的,所有我们需要再递归调用左边。import java.util.*;public class Solution { /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规原创 2021-06-30 12:04:24 · 151 阅读 · 0 评论 -
牛客-NC76-用两个栈实现队列
NC76. 用两个栈实现队列(easy)方法一:直接模拟法(自己写的)方法一:直接模拟法(自己写的)思路:stack1拿来存值,stack2拿来取值。push方法非常直接,稍微有点曲折的是pop方法,我们需要做判断:(1)stack2还有上一次stack1倒过来的值,而此时pop只需要将stack2中的栈顶元素pop出来就行。(2)当stack2为空,此时需要将stack1新增的值倒过来,再pop就行了。import java.util.Stack;public class Solution {原创 2021-06-30 11:00:26 · 94 阅读 · 0 评论 -
牛客-NC93-设计LRU缓存结构
NC93. 设计缓存结构(medium)方法一:HashMap + Queue(自己写的)方法一:HashMap + Queue(自己写的)思路:定义一个HashMap用于存放键值对,定义一个Queue记录存放时的顺序,也可用于更新顺序,定义一个ArrayList存放返回值(后面需要将其转换成数组)。直接遍历二维数组operators:(1)当操作为set,即operators[i][0] == 1时,作以下判断:<1> 当前Queue长度并没有超过k,那直接使用HashMap和Que原创 2021-06-30 09:28:44 · 132 阅读 · 0 评论 -
剑指Offer刷题记录,第八题。
剑指 Offer 12. 矩阵中的路径(medium)方法一:递归 + 回溯 + 剪枝方法一:递归 + 回溯 + 剪枝思路:本题提供了一个矩阵,矩阵是一个二维数组,需要我们在二维数组中进行搜索,为了能够覆盖所有的情况,必然要使用两个嵌套for循环。在搜索过程中,当遇到匹配成功的元素,搜索其下一元素的操作与当前的操作一致,即可以使用递归。递归参数:当前元素在矩阵 board 中的行列索引 i 和 j ,当前目标字符在word 中的索引 idx 。终止条件:返回 false:(1) 行或列索引原创 2021-06-29 22:18:00 · 125 阅读 · 0 评论 -
牛客-NC4-环形链表
141. 环形链表(easy)方法一:快慢指针(最优解)方法一:快慢指针(最优解)思路:定义fast、slow即快慢双指针,移动步数分别为2和1,如果链表存在环,那它们必然会相遇。当快指针fast到达尾部时,表示并不存在环路。/** * Definition for singly-linked list. * class ListNode { * int val; * ListNode next; * ListNode(int x) { * val原创 2021-06-28 21:50:48 · 163 阅读 · 0 评论 -
剑指Offer刷题记录,第七题。
剑指 Offer 24. 反转链表(easy)方法一:迭代法方法二:递归法方法一:迭代法思路:迭代法需要三个指针,分别是pre、cur以及nxt,用于顺序遍历链表。初始化时,pre指向空节点(头结点的next指向),cur指向头结点head,nxt指向head.next,同时由于head.next可能不存在,所以放在循环体中去初始化。迭代过程如下:(1) nxt指向cur.next(2) cur.next指向pre(3) pre移动到cur位置(4) cur移动到nxt位置退出时,返回pre原创 2021-06-28 21:00:58 · 79 阅读 · 0 评论 -
数组实现栈
数组实现栈实现栈的方式有两种,一种是数组package com.atguigu.exer;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;/** * MyInput.java: Contain the methods for reading int, double, float, boolean, short, byte and * string value原创 2021-06-28 11:08:49 · 298 阅读 · 0 评论 -
MyInput-用于字符与几种基本类型的转换
字符与几种基本类型的转换刷题中,我们经常要将从键盘读取的字符转换成基本数据类型,这个类用于对这些操作的集中处理!package com.atguigu.exer;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;/** * MyInput.java: Contain the methods for reading int, double, float, bool原创 2021-06-26 11:02:29 · 603 阅读 · 0 评论 -
剑指Offer刷题记录,第六题。
剑指 Offer 06. 从尾到头打印链表(easy)方法一:暴力法方法二:辅助栈方法三:递归法方法一:暴力法思路:直接遍历一遍链表,并使用ArrayList记录链表元素。再新建返回数组arrs,反向遍历ArrayList并将值存入arrs返回即可。/** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int原创 2021-06-24 22:55:56 · 85 阅读 · 0 评论 -
剑指Offer刷题记录,第五题。
剑指 Offer 53 - II. 0~n-1中缺失的数字(easy)方法一:二分方法一:二分思路:核心思想在于排序数组中的搜索问题,首先想到二分法解决,需要注意的是缺失的数字一定是右边子数组的第一个元素,如下图描述。图片源于class Solution { public int missingNumber(int[] nums) { // 特例 if (nums == null || nums.length == 0) { retu原创 2021-06-24 21:47:19 · 108 阅读 · 0 评论 -
剑指Offer刷题记录,第四题。
剑指 Offer 53 - I. 在排序数组中查找数字 I(easy)方法一:二分+递归方法一:二分+递归思路:其实从题干描述就知道肯定会使用二分查找,最大的问题在于怎么根据题目要求调整二分查找,可以看出如下关系式(二分最难莫过于边界条件的控制):class Solution { int count = 0; public int search(int[] nums, int target) { // 特例 if (nums == null || n原创 2021-06-23 22:11:08 · 113 阅读 · 0 评论