力扣刷题日记
Jerry8846
很笨、很蠢、正在非常努力学习的小白
展开
-
每日一题 第三十八天 完全二叉树的结点个数
所以,对于每一个结点,首先测量左右深度,若相等,则说明为满二叉树,直接返回结点个数,若不相等,则递归左右结点。思路二:利用上完全二叉树的特性,若一个二叉树是满二叉树,则它的节点数为2^深度-1。首先不管是不是满二叉树,只要遍历一遍,遍历每一个count+1就好。原创 2022-09-17 22:40:47 · 217 阅读 · 1 评论 -
每日一题 第三十七天 二叉树的最小深度
思路:与昨天基本相类似的题目,层序遍历,前序后序都可以,这里用一下前序遍历。原创 2022-09-15 22:57:16 · 254 阅读 · 0 评论 -
每日一题 第三十六天 二叉树的最大深度
解决方法:根节点入队,使得第二层也入队(之后根节点出队),遍历第二层第一个结点的时候,获取一下队伍的长度,此时队伍的长度就是第二层结点的个数,用一个for循环一次性处理掉队伍里的结点,接下来就是对第三层的处理,如此可以简单得到二叉树的深度。思路一:首先思考的是采用哪种遍历方式,深度嘛,很容易想到了层序,每层加一,那么问题来了,结点进队出队的时候怎么知道下一个是不是同一层的。原创 2022-09-14 21:46:22 · 186 阅读 · 0 评论 -
每日一题第35天 对称二叉树
思路二:一边遍历,一边比较左右树的外侧(左树.left,右树.right)与内侧(左树.right,右树.left)是否相同,参照之前的递归遍历可以很容易写出如下代码(不同点在于一次性遍历两棵树)思路一:想到了层序遍历,一个从左,一个从右,然后进行比较,但实践起来发现对于空节点位置会出现问题,如果对空节点做标记,那么遍历又无法到达终点了,因此思路一失败。思路:主要就是比较两棵子树的外部和内部是否分别相同。除了递归的方法,同样还可以用栈。原创 2022-09-13 20:09:18 · 149 阅读 · 0 评论 -
每日一题 第三十四天 实现前缀树
实现前缀树,首先构造结点,思考的要点是子节点的存储选型,如果只有字母的话可以直接使用有限数组,但我对自己要求更高一些,要实现的是敏感词的过滤,因此数目是不限的,所以我使用了哈希表作为子数据的存储其他的基本就是很简单的操作,直接拿出代码吧class Trie { /** 根节点,不存值 */ private final TreeNode root = new TreeNode(); public Trie() { } public void ins..原创 2022-05-09 00:58:11 · 105 阅读 · 0 评论 -
每日一题 第三十三天 手撕红黑树之插入
首先对插入情况做分类①一开始为空树:直接插入结点染黑即可②要插入的位置的父节点为黑色:直接插入红结点即可(红结点不改变高度,且没有发生红红冲突,所以不需要其他变化)要插入位置的父节点为红色(会发生红红冲突,若插入为黑结点又改变了高度),所以得继续往下分:(这里不考虑插入结点的兄弟节点的原因:①兄弟节点为红色,那么我们插入红结点即可,冲突来自上面的结点 ②兄弟节点为黑色,插入黑结点即可,冲突同样来自上面,所以冲突来自上面,我们对上面继续讨论即可)③叔伯(父节点的兄弟节点)结点为红色:...原创 2022-05-07 00:56:38 · 166 阅读 · 0 评论 -
每日刷题:第三十二天 翻转二叉树
思路:使用层序遍历,对于每一个结点,交换他们的两个子节点就好通过代码(java):/** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode() {} * TreeNode(int val) { this.val = val; } * Tree...原创 2022-05-06 00:39:52 · 469 阅读 · 0 评论 -
每日刷题:第三十一天 二叉树的层序遍历
五一休息了一下,今天继续开始刷题二叉树的层序遍历,其实就是广度优先的问题对于广度优先有以下通法(使用队列这种数据结构):首先让根节点入队列,然后根节点出队入到结果数组中,根节点的左侧若不为空则入队,右侧若不为空则入队。按照这个方法,就可以将广度优先的遍历打印出来了,但这道题还要求要按层分布所以每次进入队列之时,记录下此时队列的个数,这个个数就是这一层的数目,到时候按照这个个数执行多少次出队,就可以按层出了通过代码(java)/** * Definition for..原创 2022-05-05 01:07:00 · 192 阅读 · 0 评论 -
每日刷题:第三十天 二叉树的迭代遍历方法
虽然使用递归可以很简单的解决深度优先遍历问题,但是递归函数对于栈的占用太大了,很容易就造成了栈溢出。那么有没有其他方式来解决遍历问题呢?答案是肯定的,那就是今天学习到的迭代遍历方法为了便于记忆,我这里使用的是统一的迭代方法(利用栈获取正确的顺序),它有以下规则①入栈顺序要与出栈顺序相反(例如:前序遍历是:中左右出栈,那么入栈就是右左中)②在要出栈的结点之后入一个空结点作为标记(后面会讲原因)③使用根节点获取正确的入栈顺序(意思就是在每一次循环中,对于当前结点都视为根节点)④对于空的节原创 2022-04-29 11:18:03 · 140 阅读 · 0 评论 -
第二十九天 二叉树基础知识及深度遍历(递归实现)
一、基础知识1、二叉树的存储:①数组:如图,一个结点(下标为n)的左子节点为:2*n+1右子节点为:2*n+2父节点为:(n-2)/2②链表2、遍历方式按大类分为两种深度优先遍历(优先向下走),广度优先遍历(优先左右走)深度优先又分为:前序、中序、后序遍历,这里的前后中指的是中间结点的输出顺序如果为前序,那么一碰到结点就输出,如果为中序,那么优先得到左子节点,若左边为空,则输出当前的,如果为后序,那么要先往左边走,左边为空,走右边,右边为空再输出当前结点1原创 2022-04-28 09:18:01 · 615 阅读 · 0 评论 -
每日刷题:第二十八天 前k个高频元素
所得:之前没用过优先队列,这里先讲讲优先队列是什么,首先,优先队列就是一个二叉树,他维护的是父结点永远大于(或小于)子结点,因此根节点永远是最小值或是最大值。优先队列的插入结点(最小堆):首先将结点插在队伍最后(如图),例如这里插入的是4,那么4就需要与它的父节点比大小(9),此时4小于父节点,那么二者交换(称作上浮),上来之后再与新的父节点比较,还是比父节点小,所以再次上浮,再与3比较,比3小,所以插入结束优先队列删除结点:将删除结点与队尾交换,然后移除(如图),之前队尾的结点到达新的..原创 2022-04-26 23:57:30 · 365 阅读 · 0 评论 -
每日刷题:第二十七天 滑动窗口最大值
要求一个窗口内的最大值思路一:一开始想到的是我标记一个最大值,拿最大值去和下一个入队的比较,但实操起来发现,当这个最大值出窗口之后,还是得花on的时间再去求一个最大值,所以最坏情况是o(n^2),跟暴力检索也没区别了思路二:通过思路一的碰壁,我理解到了,这道题的难点在于如何维护最大值和它对应的下标,我的思路是创建一个类,类里面有值和下标,通过值去排序,那么我滑动一下,先判断一下最大值是否出列,然后再判断新来的与最大值的关系,这样子做也是可行的缺点:对比最优解,思路二首先空间消耗大一点(不是关..原创 2022-04-26 10:59:55 · 109 阅读 · 0 评论 -
每日刷题:第二十六天 删除字符串中所有相邻重复项
养生题:生成一个栈,若栈为空或者栈顶元素与当前遍历的元素不相等,则该元素入栈,否则出栈,最后出栈,生成最后的字符串(注意反向)通过代码(java)class Solution { public String removeDuplicates(String s) { //创建栈 Stack stack = new Stack(); //遍历字符串 for(int i = 0;i < s.length();i++)...原创 2022-04-24 23:29:59 · 376 阅读 · 0 评论 -
每日一题 第二十五天 逆波兰表达式求值
看题目以为多牛逼的一道题,一进去一看,中等题,好!做!思路:遇到数字入栈,遇到符号出两个数字进行运算,结果再入栈,最后返回栈顶元素非常非常简单的一题,看了一下题解,确实也是最简解法了,说明力扣的题目难度真的很有问题通过代码(java)class Solution { public int evalRPN(String[] tokens) { //创建一个栈 Stack<Integer> stack = new Stack(原创 2022-04-23 23:21:01 · 873 阅读 · 0 评论 -
可能是全网最详细讲解KMP算法中next数组的建立
全文在上一篇文章中,这里单独将next数组拎出来,因为next数组是KMP算法中最难的地方,也是为了方便更多同学搜索到,个人能力有限,有错误也麻烦指出Next数组的建立实操过代码的同学,一定知道KMP算法的最难点就是构建next数组,网上有一些已有的方案,却没有讲清楚这些方案的真正思路,所以建立next数组就是本文章的重中之重首先,我们看一下一种被广泛运用的next数组的建立方案,之后我们再去剖析每一步的其中意味,让我们更深刻的理解前人总结的方案的妙处通法:① 初始化(左右指针就位)② 前后缀不原创 2022-04-23 22:40:45 · 386 阅读 · 0 评论 -
每日刷题:第二十三、二十四天 详解KMP算法中next数组
今日不刷题了,对前两天的KMP算法进行详解,我搜遍了全网,对于next数组的建立只有说明如何建立的,却没有说明为什么这样建的,今天我们将会从暴力枚举的弊端KMP算法的引入及优势KMP算法的实现nxet数组的创建几个方面来讲解,本人能力有限,若有错误也麻烦各位大佬及时指出暴力匹配的弊端这是一道经典的字符串匹配问题给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串出现的第一个位置(下标从 0 开始)。如果不存在,则返回 -原创 2022-04-21 23:58:34 · 454 阅读 · 0 评论 -
每日刷题:第二十二天 重复的字符子串
思路:题目寻找的是一个字符串可否由某个部分重复构成,意思就是我将这些一个个小部分重新排布仍然等于原字符串,那么第一个思路就出来了我一次挪动一个字符,将其挪到最后一位,若该字符串符合题意,则总有那么一个时候,挪动的字符串构成了题意中的某个部分,那么此时的字符串就等于原来的字符串如图,该字符串由ABCD这个部分重复组成,意思就是我们将ABCD这个部分随意排序,那都等于原来字符串,上面的操作就是将第一个ABCD部分挪到最后一个ABCD处,那么怎么才能挪动呢,不管你这个部分是ABCD,ABCDEAS..原创 2022-04-21 01:30:33 · 715 阅读 · 0 评论 -
每日刷题:第二十一天 有效的括号
思路:构建一个栈,之后遍历字符串,若栈顶元素(记得空指针处理)与当前字符相匹配,则出栈,若不匹配,则入栈,遍历完之后,看栈中个数,若为0说明字符串有效,若不是0说明无效优化思路:若右括号入栈,直接返回false闲话:明天高数考试,kmp题解先搁置一下通过代码(java):class Solution { private static final Map<Character,Character> map = new HashMap<Character, Ch..原创 2022-04-20 00:25:05 · 82 阅读 · 0 评论 -
每日刷题:第二十天 实现strStr()
闲话:现在时间:凌晨两点半,我只想说KMP,我xx(爱)你题目是这样子的,我只想说,狗都知道什么意思,很简单吧,kmp嘛现学现卖立马干!干到现在凌晨两点半,不多bb了,明天再写解析和代码吧,舍友都睡了不好鹏鹏响...原创 2022-04-19 02:34:18 · 241 阅读 · 0 评论 -
每日刷题:第十九天 左旋转字符串
思路: 跟昨天的题目类似,先旋转全部,再分别旋转左边和右边时间慢大概率是因为java本身字符串不可变,所以要先变为char数组,不算变换,时间复杂度是o(n),空间复杂度是o(1),已经是最快了通过代码(java):class Solution { public String reverseLeftWords(String s, int n) { //转化为字符串 char[] ss = s.toCharArray(); //先翻转整..原创 2022-04-18 00:52:05 · 237 阅读 · 0 评论 -
每日刷题:第十八天 颠倒字符串中的单词
这道题使用api切割单词然后入栈,出栈即可解决升级:在不额外创建空间的情况下执行(由于我使用的是java语言,字符串本身不可变,所以我这个不额外创建空间是对于转化后的字符串数组说的)整体思路:先除掉多余的空格,之后整体翻转,然后每个单词翻转。 第二、三歩不难,难的反而是第一步,如何在不创建多余的空间下删除空格。其实这与昨天的题目类似:回顾昨天的题目,是删除数组中指定的数字,我们使用了双指针,左指针代表新数组的末尾,右指针代表老数组目前遍历到的元素...原创 2022-04-17 01:05:35 · 74 阅读 · 0 评论 -
每日刷题:第十七天 移除元素
思路:这种在原地修改数组的题目,都可以使用双指针解决(目前来看是这样子 的)。一个左指针标记新数组的结尾,一个右指针标记原来指针遍历到的地方若右指针为指定值,则左指针不变,右指针往后走(下一次会覆盖掉本次赋值)。若右指针不是指定值,则左右同时++;通过代码(java):class Solution { public int removeElement(int[] nums, int val) { //双指针,左为赋值位置,右为判断位置 ...原创 2022-04-15 23:18:27 · 69 阅读 · 0 评论 -
每日刷题:第十六天 翻转字符串一、二 替换空格
前面两题没什么技术含量,直接跳了这道题可以增加难度:如何在不创建新空间的情况下完成(这是扩容题的通法)思路:首先遍历一遍找到空格的个数,然后扩容数组,大小为原来长度+空格个数*2。如图构造双指针,从后往前走(从前往后的话,要移数组位置,时间复杂就变为on方了),若发现left是空格,就从后往前填入“%20”,若不是则填入当前字符。通过代码(java):class Solution { public String replaceSpace(String s) {原创 2022-04-15 00:35:58 · 525 阅读 · 0 评论 -
每日刷题:第十五天 环形链表二
思路一:跟昨天差不多的题目,还是可以一样使用哈希表存结点指针,若该节点指针已存在,则返回该指针,若不存在则往后走,若该节点指针为null,返回null思路二:双指针法,一开始有想到双指针解决,因为做过双指针的循环题目,但是解决不了入口的问题。看了题解差不多,感觉真的妙极了!大致结论就是:一个在双指针相遇的点开始,一个点在开头开始,一次各走一步,最后两个指针就会相遇在入口处。证明:快指针走到相遇点的步数:x+y+n(z+y)慢指针走到相遇点的步数:x+y同时快指针一次走两步,慢指针一次..原创 2022-04-14 00:16:55 · 498 阅读 · 0 评论 -
每日刷题:第十四天 链表相交
思路一:相交问题都可以使用哈希表解决,将第一条链表每个结点地址存入哈希表中,然后遍历第二条链表,若哈希表中包含该节点地址,则返回该节点,否则往下走,最后找不到,返回null时间复杂度:o(n+m)空间复杂度:o(n)思路一是很容易得出来的,之前也做过类似的题目,然后看了这道题的题解,才发现双指针的神奇解法!!思路二:双指针法,我们分析这道题难点就在于我们一开始的指针指向的两条链表从后往前数不是一样的位置,那么只要从后往前数是一样的位置了,我们比较两个指针是否相同,若相同则返回该指针,若不..原创 2022-04-12 23:31:27 · 368 阅读 · 0 评论 -
每日刷题:第十三天 删除链表的倒数第n个结点
思路:第一反应肯定是先遍历一遍了,然后取第总长度-n 的节点。做完之后,想这类题目大概率都能使用双指针(直觉),双指针方法:快指针比慢指针快n个结点,如果快指针是null了,那么慢指针指向的结点就可以删除了,又根据我们之前总结的原则,删除的操作应该输入被删除结点的前一个,所以最终得出快指针要比慢指针快n+1个结点,最后思考快指针是否出现空指针问题,因为这道题规定了:再加上最后要求返还链表头,所以我们创建一个虚拟头结点,也就是说从虚拟头结点走n+1歩,这个过程绝对是安全的,因此大胆走!...原创 2022-04-12 00:20:54 · 740 阅读 · 0 评论 -
每日刷题:第十二天 两两交换链表中的结点
闲话:今天的“中等”可比昨天的“简单”简单太多了哈哈思路:先判断是否能交换,每次交换封装为一个函数,交换完之后往后走,再判断是否能交换即可为了保证最后返还的头结点,所以我们还可以加一个虚拟头结点实现代码(java)/** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode() {} * L..原创 2022-04-11 00:17:08 · 510 阅读 · 0 评论 -
每日刷题:第十一天 设计链表
闲话:千万不可小瞧这类题,看一眼就知道怎么做,但是指针越界真的烦死我了,小补小修了两个小时!!思路:查找就走到当前一位,添加删除就走到这一下标的前面。那么怎么走,不会那么抽象呢,首先我们加一个虚拟头结点(昨天的结论),那么头指针就作为了0的开始,这样子下标就完全对应上了,之后将该链表完全类比数组,如图,类比数组这样子走,会走到第index位那么我再对昨天的结论做出一个改进:对于链表的遍历①若是增加或删除操作,永远是走到删除(添加)位的前一位②要创建一个虚拟头部节点...原创 2022-04-10 00:50:11 · 86 阅读 · 0 评论 -
每日刷题:第十天 移除链表元素
闲话:昨晚喝了点小酒,回到宿舍已经一点多多了,倒头就睡了,今天下午先补上昨天的,今天晚上再写今天的题目(不喜欢连续刷题)很简单的删除链表元素的操作,但有一点细节需要注意思路:一个while循环对整个链表进行遍历,到达每一个结点,用一个小循环保证当前结点指向的下一个节点的值必须不是val,最后返回头部节点细节:对头部的处理,大家可以看到我的思路,对当前结点的值是无法判断的,所以对于头部节点是没有办法的,因此我在最开始添加了一个虚拟头部节点,让头指针指向虚拟头部节点,这样子原来的头结点就变为..原创 2022-04-09 14:15:59 · 422 阅读 · 0 评论 -
每日刷题:第九天 赎金信
很简单的一道题,判断a数组的字符能否由b数组的字符组成,且b数组的字符不可复用思路:构建哈希map,key放字符,value放出现的次数,那么先遍历一遍b数组,若当前字符存在,则value + 1 ,若当前字符不存在则put进去;之后遍历a数组,若当前map中没有当前字符或者当前字符指向的数字为0,则直接返回false,否则当前字符指向的数字-1;遍历完返回true优化:翻到下面,发现数组只有小数构成,这就更好做了,直接使用数组承担哈希表的功能,数组下标即为对应的ascill码%25的值,数组值..原创 2022-04-08 00:58:09 · 924 阅读 · 0 评论 -
每日刷题:第八天 四数相加2
四数相加,又是加加加一类的哈哈,与之前三数之和四数之和不同,这道题没有要求不能重复,也就是说我们不用对他们进行排序了思路:一开始想的是三次遍历加哈希值运算,然后看了题解里的一句话也就是说x个数相加的题目,只要不要求有序,那么我们就可以把他们分为两组,使用map容器,key放相加之后的值,value放出现的次数,然后在第二个map里面寻找key = -key1就好,这是时间复杂度最低的做法那么为什么是一半左右呢,我们简单举个例子就能解释,例如一共四组,那么加入 1-3分,那么其中一组map..原创 2022-04-07 00:50:44 · 416 阅读 · 0 评论 -
每日刷题:第七天 反转链表
很简单的一道题目,一开始就想到重新创建一个链表,然后下一个节点的next指向上一个节点就好,时间复杂度是o(n),但空间复杂度是o(2n)虽然也还是o(n),但确实也还能优化,思路:使用双指针,使后指针指向前指针的内容,结束条件:后指针为空,另外在做一下特殊情况的提前排除就好通过代码(java)/** * Definition for singly-linked list. * public class ListNode { * int val; * ListN..原创 2022-04-05 22:44:40 · 991 阅读 · 0 评论 -
每日刷题:第六天 四数之和
跟三数之和差不多: 首先要保证不重复,因此数组要先排序,之后用两个for循环,剩下两个位置使用双指针,总之就是要在三数之和的基础上加上一个for循环,不过要注意的是:前面两个for循环带来的重复问题,即第一个数字和第二个数字相同重复出现的情况,因此在三数之和的基础上添加一个:当前面两个数字相同时,判断集合中是否已存在这个四元组,若不存在再加入实现代码(java)class Solution { public List<List<Integer>&...原创 2022-04-05 00:41:22 · 1020 阅读 · 0 评论 -
每日刷题:第五天 三数之和
闲话:一开始想用哈希表做的,没想到这道题最难的居然是去重!题意:找出不重复的三个数字组合使得三数之和为0法一:暴力枚举!!为了防止重复,先对数组排序,之后使用三次循环,保证每次循环取的数字与之前的不同,即可去重,时间复杂度o(n立方)(时间超了)法二:双指针法如何想到使用双指针:当一个数字不断增大时,另一个数字不断减小,即可使用双指针首先我们定下一个数字,那么剩下两个数字之和就是一个定值,那么其中一个不断增大时,另一个就一定不断减小。因此我们先对数组排序,如下图,定下数...原创 2022-04-04 01:23:05 · 464 阅读 · 0 评论 -
每日刷题:第四天 快乐数
由题意得最终的结果就是循环或者等于1法一:分析题目可知,循环的原因是出现了重复的数字,因此使用set容器判断是否重复或者结果是否为一,若为一则返回true,若出现重复数字,则返回false这个方法很奇怪,我用我的方法写出来会报错,但是测试错误示例错是正确的,希望有大佬帮忙解答一下法二:使用快慢指针判断是否循环,原因是这个题目本质上各个结果之间构成的是一个单向指向的关系即链表,因此可使用快慢指针,若快指针为一则返回true,若慢指针与快指针重逢(产生循环)且不为一返回false..原创 2022-04-02 22:43:41 · 599 阅读 · 0 评论 -
每日刷题:第三天 两个数组的交集
据题意:核心是比较是否相同,所以在哈希表和红黑树中选择,而这里的数字没有大小限制,因此容器最后选择HashSet或TreeSet思路:将数组一输入hashset中,然后遍历数组2,检查set中是否包含某位数字,包含则将数字输入到结果数组中实现代码(java)classSolution{publicint[]intersection(int[]nums1,int[]nums2){//建立一个哈希表Setset=new...原创 2022-04-02 00:44:26 · 847 阅读 · 0 评论 -
每日刷题:第二天 有效的字母异位词
一道挺简单的题目,考察的是哈希表的使用题目的意思就是问两个字符串的字母类型及类型对应的个数是否相同,很容易就想到使用哈希表思路:构造一个26大小的字符数组,遍历第一个字符串,读取对每一个字符模26,得到该字母在数组中的位置,该位置的数值++,再遍历第二个字符串,同样的操作,但数值--;最后遍历一次这个数组,看是否出现非0,若有非0,则返回false,若全为0返回true下面为通过代码(java)classSolution{publicbooleanisAnag...原创 2022-04-01 00:21:18 · 443 阅读 · 0 评论 -
每日刷题:第一天 螺旋矩阵II
这类题目难点在于模拟顺时针旋转的时候容易乱,所以要先定好旋转的规则。我的规则就是,先转外圈,再转内圈如图为一圈(并且要按如图的走法,最后一个格子留给下条边) (即:左闭右开)每圈走四条边,每条边走一个步长(初始步长为n-1,每走一圈,步长-2)按照以上的走法走完一圈后,会回到初始位置,所以要将位置(x,y)移到下一圈的初始位置要走的圈数为:...原创 2022-03-30 23:44:59 · 251 阅读 · 0 评论