以下为代码随想录算法训练营优质讨论内容
代码随想录算法训练营
以下为代码随想录算法训练营优质讨论内容
刷题建议
●代码随想录目前有前半部分都有视频讲解,一定要先看视频,事半功倍。
●一定要了解自己做题用的语言,或者说,原本可能不熟,但在做题过程中,碰到一些语法问题、容器选择问题等等,就随时地百度、google一下,这样刷题一圈下来,对语言的掌握程度也能提高不少
●几乎所有的代码问题都可以通过打日志来解决,哪里不懂打哪里的日志。
●如果对递归不是很熟悉, 就主要先学一下思想, 设计简单case, 进入到递归的最后一层然后执行逻辑慢慢倒着推一遍就可以知道逻辑了, 以后才可以正着就写出, 部分题目递归的本质是把每个问题都分成子问题, 子问题都解决了就等于解决了主问题。有点大家后面学的动态规划的意思。学树的时候大家就更能有这个感受了不着急哈 From 芒果冰冰
●遇到奇怪bug无法解决的时候卡哥建议:很多录友刷题的时候 也会有这样的问题,就是 好不容易代码写出来了,怎么改都不对,又不舍得删自己的代码,然后怎么看也看不出问题。 我也遇到过这种情况,我的经验是,代码全删连备份都不要, 重新写。
●多考虑一下自己代码的鲁棒性,进入循环用到之前之后都打一下日志啥的,是很好的一个发现错误的方法!
●有的录友会因为各种各样的事情没跟上进度,时间紧张的录友 可以只把题目AC,博客简单记录思路也可以,甚至是 只把题解看一遍 了解一下思路也可以,但一定要跟上进度,这样才有节奏,如果 大家每日任务落下了 就会一直落下了,很难再追上,然后 自己进度就越来越慢,更不上节奏,成为群里的旁观者。 所以 大家 每道题目 理解的深度上可以做 剪枝,哪怕是今天没时间了,就把今天安排题目的题解读一遍,了解一下整体思想,看看大家讨论内容,这样也是跟上了,周日自己在抓紧时间补代码练习。训练营结束至少也对各个专题的算法解法有一个大体了解。 总比落下进度,自己也不追了,成为群中旁观者 强得多。
● “KMP算法 和 day10 安排的题目(kmp的一个应用),一刷 录友们 可以适当放过,或者了解一下 算法原理就行,毕竟比较难,等二刷的时候在重点啃
●坤哥路线分享:第一次刷的时候,可以先根据Carl哥的题解走一遍,熟悉题型,二刷的时候开始个人归纳总结,然后找类似题目多练练,得出个人的题型模板,在后面就偶尔打打周赛,做到灵活应用。建议大家也可以参加一下周赛
如何Debug???(有问题会继续更新)
debug的思维很重要,如果没有这种思考方式,下次 遇到 代码问题,依然还是不会,不能靠自己解决问题。 这是 鱼和渔的关系
最近发现很多录友还是不太会debug不能靠自己找出代码的问题故写一下方法
说明 : 如果你打了以下日志还是没找出问题,则可以利用idea或者其他编辑器自带的断点和debug工具调试,当然可以细化debug的粒度,记住核心是先定位问题的行数,出现的轮次,在那个轮次当中进行检查
一个排查问题的思路,你的报错 一大串 你也分不清是哪里出错了,这种情况下,你把你的函数一个一个的删(当然之前可以先备份一下),删到哪个函数,没报错了,再去填新的函数,不要 整段代码一起看。
例子1
例子二
例子三
例子四
例子五
关于看题解
很多同学总是因为自己没有办法一次性把题目A出来而感到沮丧,并且会为了自己需要去看答案而感到自己很菜
我想说的是:一刷不要耻于去看答案或题解,毕竟学习谁也不是生来就会,除非你是天才,保证自己二刷三刷可以不看就有思路或者直接写出来,就是自己最大的进步,刷题也是一种学习的过程,需要循序渐进。
如果一道题你二十分钟没思路,或者说你写出来了但是debug了几十分钟,不要犹豫,直接打开卡哥的代码随想录,直接看思路,或者直接对照代码一行行检查,往往是最高效的排错过程
一般来说出现bug的地方也只是一些微小的细节,注意得多了自然以后经验丰富了bug率自然也会降低的。
蓝桥杯怎么准备?
●刷力扣刷蓝桥杯真题,达到可以力扣周赛1900的水平就差不多能拿个省一吧,蓝桥杯主要就是暴力法,也就是dfs,bfs,回溯比较重要,其他的都是暴力做就好了满分除了签到起码要ICPC铜牌实力了现在,多总结题型多刷题,当然你现在还是先把代码随想录过一两遍,这是以后做题的思路基础
●主要还是建议做真题吧,B组的话就时间换算那些还是必须要会的暴力能拿的拿到,A组的题就比较难,除了签到基本上都是暴力拿满,只要有一道能想到个接近满分的次优解就能省一,OI赛制按最后提交的答案算分如果%90能拿30分,%10能拿50分就选%90的,能想出最优解的话起码蓝桥真题得做不少
●蓝桥杯几个重点: BFS,DFS,回溯,递归,二分, dp(没事大家一般都做不出来这个) B组加一个时间转换,进制转换 这些是最重要的(暴力还得回溯DFS呢对吧,二分稍微优化一下得分就更高)
字符串哈希解决不会KMP的小伙伴的烦恼
字符串哈希博客
排序算法(重点掌握归并快排堆排)
排序算法详解(堆,归并,快速排序最简及理解写法; 芒果冰的bolg)
十大排序从入门到入赘
十大排序算法超全大综合,动图演示,你真的值得拥有!
工具分享
●Excalidraw | Hand-drawn look & feel • Collaborative • Secure
大家平时刷题可以用这个网站画草稿图帮助理解!如果看题解很蒙或者思路不清晰的时候,跟着程序处理流程画一个图,90%的情况下都可以解决问题!
●Data Structure Visualization
数据结构和算法可视化可以看这个网站,还可以互动添加元素等,非常直观让你快速理解!
●Deque (Java Platform SE 8 )
这是Java的Deque容器的官方文档,这个容器非常重要,作为Java选手一定要牢牢掌握。他是一个双端队列,常用来当栈和队列使用,api也是非常丰富,刷题过程中出现频率很高!之后就是关于看文档的问题,大家遇到api不清楚的情况下第一时间要学会去看官方文档,这是第一手资料,往往是最准确的,包括大家之后工作中遇到问题也要养成这种能力,还有阅读英文文档的能力。
●如何将力扣上面的题目拉到idea里跑?
有第三方插件可以安装: Leetcode editor
●力扣插件:
ahttps://github.com/zhang-wangz/LeetCodeRating 可以显示题目难度对应的leetcode周赛难度分(如果这道题曾经在周赛中出现过)
bhttps://github.com/XYShaoKang/refined-leetcode 可以帮助记录做题时间,打开做题页面就会开始计时,这样可以帮助大家知道解出这题花费了多久,也可以更合理地安排时间
day1
讨论知识点
●最重要的就是分类讨论好二分,二分看着好写边界case还是需要测试的哈
●大家需要注意二分的几种情况
○当l = 0, r = n的时候因为r这个值我们在数组中无法取到,while(l < r) 是正确写法
○当l = 0, r = n - 1的时候因为r这个值我们在数组中可以取到,while(l <= r) 是正确写法 主要看能不能取到这个值
●二分法有多种写法,末尾是开区间闭区间都可以解出寻找单个元素和寻找边界的题目,只需要注意相应的是l < r还是l <= r,每次取mid还是取mid加减一即可。建议理解后背熟一套模板,不要搞混。
●关于二分法和移除元素的共性思考
关于二分法和移除元素的共性思考这两题之间有点类似的,他们都是在不断缩小 left 和 right 之间的距离,每次需要判断的都是 left 和 right 之间的数是否满足特定条件。对于「移除元素」这个写法本质上还可以理解为,我们拿 right 的元素也就是右边的元素,去填补 left 元素也就是左边的元素的坑,坑就是 left 从左到右遍历过程中遇到的需要删除的数,因为题目最后说超过数组长度的右边的数可以不用理,所以其实我们的视角是以 left 为主,这样想可能更直观一点。用填补的思想的话可能会修改元素相对位置,这个也是题目所允许的。
●其实二分还有很多应用场景,有着许多变体,比如说查找第一个大于target的元素或者第一个满足条件的元素,都是一样的,根据是否满足题目的条件来缩小答案所在的区间,这个就是二分的本质。另外需要注意,二分的使用前提:有序数组
●小tips:
○根据题目的数据量范围选择合适的算法,比如数据量是10^5,那就只能使用O(nlogn)复杂度以下的算法了,使用O(n^2)是会超时的;而如果数据量只有100或者1000,则可以果断的采用暴力方法(一般是O(n^2))进行求解
○二分的最大优势是在于其时间复杂度是O(logn),因此看到有序数组都要第一时间反问自己是否可以使用二分。
今日打卡的博客分享
算法记录 | Day1数组基础给出难点思考过程和总结过程python代码,也有了自己的收获
Java数组笔记及算法练习多了一些拓展的题目,和自己的思考,大家也可以做一下Java
代码随想录算法训练营第一天 | 704. 二分查找、27. 移除元素给出写法思考和复杂度以及自己的收获c++
比较简单,算上博客大概2-3h,网速不行... 将思考过程完全体现了出来,重点突出,总结和注意点很到位
找一找刷题的感觉 多种方法都尝试了,加油加油
二分查找+移除元素 注释很详细,排版上还可以优化
很细,注释很全,看不懂算我输(求推荐) 这位录友的格式很不错~对于时间复杂度的分析很到位,值得大家学习
没被分享的小伙伴也不要灰心,可能不是你写的不好只不过可能我偶尔会犯傻一两下哈哈,希望大家理解一下,坚持打卡写上收获思考总结,一定可以进步的! 芒果冰冰也是刷了几个月总结才形成自己体系进步的大家也可以!
day2
讨论知识点
●滑动窗口:本质是满足了单调性,即左右指针只会往一个方向走且不会回头。收缩的本质即去掉不再需要的元素。也就是做题我们可以先固定移动右指针,判断条件是否可以收缩左指针算范围。大家可以好好理解一下。From 芒果冰
●为了特殊情况的专门写判断语句效用有多少?是否需要考虑特殊的情况?
需要考虑特殊情况,比如容器/数组/指针是否为空等,可以在考虑到特殊情况后先额外判断写出来,整体逻辑写完后看是否能和一般情况进行合并
今日打卡的博客分享
【代码随想录Day2】有序数组平方+最小子数组+螺旋矩阵II这个录友写的很不错哦, 螺旋矩阵还进行了可视化
Day2 数组:977.有序数组的平方 209.长度最小的子数组 59.螺旋矩阵Ⅱ小伙伴的分析画图很不错,滑动窗口的解题关键总结,排版也不错 c++
【刷题笔记day2】左右指针、滑动窗口、模拟分析了复杂度,重点是拓展了很多题目给大家可以去尝试做一下 python
反证法证明, 抓住定义的意义,不惧Corner case, 抓住循环不变量 | 代码随想录算法训练营第2天| 977. 有序数组的平方、209. 长度最小的子数组、59. 螺旋矩阵 - ywh-pku - 博客园 这位录友还用了反证法进行了证明「有序数组的平方」,大家可以看看他的博客应该会很有收获,非常优秀的一位录友。
虽然这些题之前做过,但是没有真正掌握,这次连自己写及看视频、文字讲解将近4个小时,写博客花了2个小时左右 很认真很用心,大家相互学习,加油鸭
代码注释非常详细,提供螺旋矩阵不同于代码随想录上的方法,非常容易理解 这位录友依旧用心~数组的总结也不错,值得学习~
day3
讨论知识点
●注意点:指针问题, 大家今天写删除链表题的时候经常少了else判断, 链表首要想好指针是怎么移动的,是否会移动会访问null即可
●
●大家遇到问题的时候对于链表问题可以多用笔画画图,这样会加深你对指针和节点实体的理解,代码的鲁棒性如何通常可以利用边界case尝试,今天很多人都是因为空指针的错误其实大多是一些if,while中不小心取到了空和循环次数和条件有关这种可以设计简单case比如1-2-3-null这种手动画图走一遍自己的代码就解决了。
●大家平常遇到不会的问题可以自己先用输出语句debug一下力扣是支持的哦,遇到问题一般自己先输出debug,解决不了设计简单case手动debug(一定要是简单case,因为手动理解深但是麻烦),再解决不了群里问别人这样是比较好的,debug也是我们写算法的一个能力,这个能力和边界case的思维对大家的工作也会有一些帮助。
●链表一定要分清节点和指针的概念 new ListNode()是真实存在的一个节点, head = new ListNode() 相当于 head指针指向了一个真实的节点, node = head, 相当于node和head同时指向了这个真实的节点
●链表相交的节点为啥不是数值相等的节点而是指针相等的节点?
首先不要把值和节点的概念混淆起来,节点是一个实例,占用一块空间;值只是它的成员变量。
值怎样和节点本身没有任何关系 一个实例只由它的地址唯一确定。
就像一个数组的两个位置,它们里面可以数值相同,但是并不是同一个地址。
或者说,本来就不是比较节点相不相等,而是比较这两个指针是否指向同一个地方。
●大家尽量不要去动虚拟头节点,因为虚拟头节点本来就是个工具节点,操作后面的节点本身就好了哦
●大家空针异常优先看上面debug的方法,节点前debug判断一下是否为null来定位!
●while复杂度分析主要看内部总共执行多少次,不是看跟for嵌套就成了On2,滑动窗口就是On
●加入滑动窗口中有负数怎么办?
如果有负数的话感觉也不能用滑动窗口了,因为有负数的话无论你收缩还是扩张窗口,你里面的值的总和都可能增加或减少,就不像之前收缩一定变小,扩张一定变大,一切就变得不可控了。如果要 cover 所有的情况,那每次 left 都要缩到 right,那就退化为暴力了哈哈。
● 寻找链表相交节点的题,python解法中提到了一种两个指针分别依次走两个链表的思路,其本质上是链表拼接,详情可以参考题解
● 涉及到修改字符串的O(1)算法理论上是只对字符串可以修改的编程语言成立的(如C++),对于其他编程语言通常参数会给成字符数组的形式
今日打卡博客分享
代码随想录第三天 || 链表理论基础 || 203.移除链表元素 || 707.设计链表 || 206.反转链表链表理论基础和题目的思路解析分析都很到位,也有总结收获,对自己以后解题的思考Java 小建议:代码风格可以改进一下比如赋值不要写val=1等号两边可以加空格还是有必要的哈
代码随想录算法训练营第三天 | 203.移除链表元素、707.设计链表、206.反转链表很不错的一个博客,内含链表总结!!!
窗外日光弹指过,席间花影坐前移 笔记很完整,全手写笔记,对链表的变化过程画图描述,很清晰。链表墙裂推荐画图!另外标题很诗意~
第三天 | 203.移除链表元素、707.设计链表、206.反转链表 递归迭代法分析很到位,笔记风格美观
【代码随想录 | day03】(JavaScript)链表理论基础&203.移除链表元素、707.设计链表、206.反转链表 基础知识,问题,总结,发散思考很多
第一次画图贡献给ipad, 牛p坏了叉个腰🦖🦖 ipad画图很到位
对于反转链表从前向后的递归方法有更详细的注解 很强的一位录友,博客风格好评~
day4
讨论知识点
●今天的题目的环形链表大家有一些人不会数学方法的话芒果冰冰这边提供一种只需要数环节点个数的方法哈, 因为保证了fast节点比slow节点间距X个节点(环的节点个数),所以相遇一定会在链表头哈
●
●然后发现大家经常会有bug发代码, 我可以偶尔看到了帮你解答, 但是这个锻炼不了大家的debug能力会锻炼我的哈哈,这边能给出芒果冰冰debug的方法:链表问题可以在循环中逻辑执行前打一次输出语句,执行后打一次输出节点值val, 符合你的预期在增加打输出node.next.val(如果你需要知道后面连接是啥),空针就代表你断链了或者其他错误了, 然后这样慢慢增加找, 还有一种就是利用手动画图debug,记得自己学链表的时候经常画图设计简单case边界case来调试,现在写链表的题都是可以脑子有链表图debug了哈哈,可以尝试一下哈各位。
●最后如果大家觉得自己的链表学的不错可以了,这边给出几道挑战题目:92.反转链表II(反转链表的进阶,也是做后面那道题的前置知识),25.k个一组链表反转(面试高频hard,注意断链反转的操作不然就会成环) 。
●大家在遇到无法定位头节点,头节点可能被移动删除导致定位失效的时候可以考虑用虚拟头节点,并不是每道题都要用的!!!!
●很多同学在 node.next.next空指针,主要原因就是 next可能为null 在用这个之前优先考虑
●找环形链表的入口时,为什么 n 可以直接取 1 呢?
○
○我是这样理解的,就是如果相遇前快指针在环中转了不止一圈,比如说转了 5 圈,导致转多圈的原因就是 x 比较长,而环的周长可能比较短。所以最后我们在找入口的时候,两个指针分别从起点和环相遇点开始移动,如果是多圈的情况,那在这个移动过程中从相遇点开始移动的指针也会转多圈,就像公式里写的,x是包含n-1个周长加上 z 的,所以我们可以将这部分在 x 抵消,也就是假设 n 为 1,此时从相遇点开始走的指针也还是在原位出发(省去了转多圈的操作),最后结果还是一样的。
今日打卡博客分享
✅✅代码随想录算法训练营Day4 | | 24. 两两交换链表中的节点 ,19.删除链表的倒数第N个节点 , 面试题 02.07. 链表相交写的非常好的一个小伙伴,风格也有点幽默哈哈,有图解收获原因赞!
代码随想录算法训练营第四天 | 24. 两两交换链表中的节点、19.删除链表的倒数第N个节点 、面试题 02.07. 链表相交、142.环形链表II、 链表总结这个小伙伴解法就比较多了,引用总结也不错, 总结了一些链表的常用方法
人如果没有梦想,跟无忧无虑有什么区别 还是这位手画链表的录友,非常值得学习
放弃很容易,但坚持一定很酷 多解法,思考过程,注意点面面俱到,bolg一如既往地优秀
链表:手中无环 心中有环 (拓展) 画图多了便可以心中有环!
第四天|24.两两交换链表的节点、19.删除链表的倒数第N个节点、面试题 02.07. 链表相交、142.环形链表II 笔记中对环形链表的画图推导很漂亮!
没被选上的小伙伴也不要灰心,真的不是你的问题,坚持打卡的你超棒的诶拜托!(比心)大家的打卡希望能有自己的收获, 总结, 复杂度分析, 部分思路图解, 打卡最后的最终目的都是给自己看的嘛哈哈 加油哦各位, 还有部分没被选上的录友的打卡也不错大家可以去打卡统计中查看哦!
day5
休息日
今日打卡博客分享(有录友在做总结~)
长恨此身非我有,何时忘却营营 数组和链表的总结,很漂亮
●大家没跟上进度的要赶上进度了哦! 赶上进度的人可以提前预习接下来的内容或者做一下上面留的两道思考进阶题目了哈!
●今日进阶:82. 删除排序链表中的重复元素 II(连在一起你怎么删除?) 328. 奇偶链表
●没打卡的同学抓紧打卡了哈
day6
讨论知识点
●大家今天最大的疑惑好像就是map的复杂度怎么算哈哈,一般n个元素map的复杂度就是On哦,不需要想得太复杂了,冲突的空间并不会造成一个量级,改变n前面的常数不会影响空间复杂度哈
●提醒!熟悉好map, set的API哦
●大家不了解c++语法的可以看一下郭炜老师的视频(中国大学mooc)
●相交链表的数学证明过程
今日打卡博客分享
✅✅代码随想录算法训练营Day6 | | 242.有效的字母异位词 ,349. 两个数组的交集 , 202. 快乐数 ,1. 两数之和小伙伴分析了难点,易错点,细节,收获, 图解了map不错哦,建议可以分析一下复杂度哈哈
算法训练Day5 | LeetCode:242. 有效的字母异位词(数组作哈希表);349. 两个数组的交集(Set作哈希表);202.快乐数 (Set作哈希表);1. 两数之和(Map作哈希表)写的很好哈,复杂度难点收获,写题的前置知识点都给出甚至还有引用(๑•̀ㅂ•́)و✧建议学习!
代码随想录第六天| 242.有效的字母异位词、349.两个数组的交集、202.快乐数、1.两数之和拿到题都会先给出自己的思路,错了也从中分析原因,如何得到的正确思路的分析过程,建议分析复杂度哈,也给出自己的收获
_5LeetCode代码随想录算法训练营第五天-C++哈希表 这位录友较为系统的分析了哈希表的性质,整理也较为全面~
day7
讨论知识点
●今日大家基本都是讨论bug,发现大家还是很容易bug卡住,推荐看一下上面卡哥和我个人给出的方法哈,找bug能力是非常重要的非常重要的非常重要的!!!继续加油各位!
●对于continue和break在三数之和的区别: continue是下一个i 还存在有可能的情况, break是无论后面多少个i我们是确定不会再出现这样的情况了
●三数之和去重为什么碰到相邻相同的要元素跳过:
一个是因为之前已经判断过,不必再判断,还有一个是因为必须要减枝,不然会超时,还有就是题目要求不能重复,再次执行会导致重复添加数据
●四数之和里群里针对剪枝的if语句进行了讨论,在第二层剪枝中使用if(nums[k] + nums[i] > target && nums[i] > 0)剪枝范围会更大~ (原本是if (nums[k] + nums[i] > target && nums[k] + nums[i] >= 0))大家视自己理解方便进行选择即可~
今日打卡博客分享
算法训练Day7| LeetCode454. 四数相加II(Map作哈希表);383.赎金信(数组作哈希表);15.三数之和(双指针);18.四数之和(双指针)
这个小伙伴写的很好哈,思路代码实现复杂度收获都给出,思考过程比较完善的,部分题目还有图解很棒鼓励!代码随想录刷题Day07|LeetCode 454.四数相加II 383. 赎金信 15. 三数之和 18. 四数之和 思路和图解详细的解释了三数之和的过程, 大家搞不明白的话可以看一下这位录友的哈
三数之和,梦破碎的地方,赎金信是为了安慰我出的吗 三数之和从哈希到双指针的思考过程完善,对去重的逻辑体现的也很详尽~
这个今日打卡博客分享一般只会找当天写完的录友哦因为要当天发,也有的录友后面会补上我看明显大家有的人还没赶上进度,录友们也可以看看前几日求推荐的录友哈~
day8
讨论知识点
●空间问题-> Java和python语言的字符串需要额外空间是因为语言本身设计,小伙伴这里用到的额外空间是没关系的
●考虑到debug很多小伙伴未掌握已经在上面写了一些常用细则,小伙伴可以补充!
●有录友提问了python的字符串为什么要转成list:python的字符串是不可变对象,做题的时候一般都会转成list便于操作
今日博客分享
算法训练Day8| LeetCode344. 反转字符串(双指针);541. 反转字符串II(模拟);offer5. 替换空格(双指针后序);151.反转字符串中的单词(综合);off58.左旋字符串还是这个小伙伴一如既往的好哈, 大家都可以学习这个小伙伴的博客, 写的很棒!
全部秒杀 一如既往地思路清晰,注释完善 天天两点半,真就拿命肝啊 有被感动到,注意身体~
day9
讨论知识点
●发现很多小伙伴都无法理解kmp, 其实我一开始学的时候也理解不了, 主要是理解好next数组的创建和回退的过程就好了哦!下标也有很多种写法大家记住一种自己写的习惯的就好了。
●考虑到大多数小伙伴理解不了kmp,我自己其实说实话也经常会忘记kmp怎么写,但是能理解他的思想,所以真的不想学kmp的小伙伴我这边给一个字符串哈希算法的模板,也给出了证明,是我很早之前写的一篇博客,大家要是无法理解或者怎么都记不住的话直接背字符串哈希的模板简单理解一下也可以解决力扣上所有kmp的问题了哈 ,在最上面会给出字符串哈希的博客。
今日博客分享
算法训练Day9| LeetCode28. 找出字符串中第一个匹配项的下标(KMP算法)这个小伙伴写的kmp理解思路和分析很不错, kmp本身也是一个比较难的算法,想学习的像伙伴也可也看看哦!(ง •_•)ง
KMP算法总结 对kmp总结得不错嗷,几个关键问题都给出了解答 kmp拿下(对while循环那部分理解不清晰的,推荐b站up凡三岁爱学习 求next数组的视频 图解过程部分 豁然开朗),周日得把之前题写一下,以免忘记 推荐! KMP神中神,感觉第二题思路上要比第一题难一些,主要得考虑清楚重复子串是如何构成字符串的 对重复子串的思路分析很好
day10
讨论知识点
●今天大家好像都在补东西或者休息了,讨论内容不多, 字符串哈希的做法的P是一个经验值,总的思想就是在O1内可以得出一个字符串的哈希值!
●队列和栈, 要分清楚peek, poll, 性质就很简单的先进先出和先进后出。
今日博客分享
算法训练Day10 | LeetCode459. 找到重复的子字符串(KMP算法的应用);字符串总结;双指针总结 啊对又是这个小伙伴可以看出他的博客真的很不错,图解分析拓展都很棒!
2道简单题。愣是大半天 形象的图解~ 还需要复习 了解了先入后出先出后入还需要了解怎么设计的逻辑 博客风格极简美,代码美观,注释详尽 当第二个队列得知自己只是备胎而且还可能因为空间复杂度太高要被换走的心情是什么样的
day11
讨论知识点
●栈,主要就是想好入栈出栈的时机,常见使用:单调性栈,树的迭代遍历,计算器问题,括号问题等等
●队列,先进先出,常见使用:BFS, 树的层序遍历等等
今日博客分享
算法训练Day11 | LeetCode232. 用栈实现队列(模拟);225.用队列实现栈(模拟);20. 有效的括号(栈应用);1047. 删除字符串中的所有相邻重复项(栈应用) 又双叒叕是这个小伙伴的博客,一如既往的好哈,继续加油!
Day11.逆波兰表达式求值、有效括号_izwmain的博客-CSDN博客
里面有小伙伴的踩坑分享!
day12
休息日
●大家没跟上进度的要赶上进度了哦! 赶上进度的人可以提前预习接下来的内容哈!
●没打卡的同学抓紧打卡了哈
day13
讨论知识点
●今天的问题主要是大家搞懂单调滑动窗口这个问题,如果看不懂也可以先放着毕竟滑动窗口最大值是hard,等大家懂了单调栈理解这个题会更简单,思想还是之前总结的滑动窗口思想,去掉不需要元素,这边单调滑动窗口就是需要再深入利用单调性去掉一些不需要的元素想清楚就可以啦!
●优先队列就是堆的一个利用,Nlog(堆大小)来add or poll,理解清楚这个就好
●大家对大顶堆和小顶堆的定义方式有点迷惑,看下下面的代码:
○这里我们用优先队列实现大小顶堆,new一个PriorityQueue类后,我们在构造函数中传入了(pair1, pair2)->pair2[1]-pair1[1],这是一个lambda表达式,用来定义大小顶堆。在Java中的涉及排序的,我们一般会自定义一个比较器,用来定义升序和降序的规则,(a,b)-> a-b 是升序,反之是降序。可以理解为:参数为(a,b)的函数,如果结果为负数,就不交换两者的相对位置;结果为正数,就交换。然后代入一个最简单的冒泡排序算法场景,就可以理解通了。大家可以再去了解下Comparator的写法。
○如果还是非常蒙,怎么办,那先记下结论,先会用,之后再去回味就会领悟了,结论是:
■(a, b) -> a - b 升序
■(a, b) -> b - a 降序
●C++函数指针与仿函数:自定义排序规则 关于C++的一些自定义排序规则方法
今日博客分享
代码随想录算法训练营第13天 |栈与队列总结 150. 逆波兰表达式求值 239. 滑动窗口最大值 347.前 K 个高频元素 小伙伴写的不错也有一些推荐题型,每道题目的理由思考也有!
代码随想录刷题day13 | 239. 滑动窗口最大值、347.前 K 个高频元素 小伙伴写的还不错啦, 建议添加上自己的思考和收获哈~
这两道题有点难,重要的是理解 思路逻辑非常清晰,代码风格很棒(python)
day14
讨论知识点
●给出一个以前序为例子画图debug方法 先画出树的结构,然后你自己的笔就是一个指针,然后笔需要指向当前的处理层,然后前序遍历就是先执行当前层,也就是把当前层的val加入答案List,然后你如果递归了左子就笔移动到左子,上一层的逻辑记住执行到了第几步,当你处理完左子会回到上层,也就是笔指到上层,此时从你刚刚的位置继续向下走,此时你用笔(指针)对这你的代码记住层数和逻辑执行到第几行移动一遍就知道了
●树递归最重要的是自底向上的思维处理最底部的子问题依次向上处理,初学者建议画图感受这个过程
今日博客分享
代码随想录训练营第14天|二叉树的理论基础、递归遍历、迭代遍历和统一遍历__忆昔的博客-CSDN博客
这位小伙伴还有丰富的配图,非常用心了!
二叉树的遍历是后面题目的基础,要理解透彻 还是lanyuan大佬,python代码注释详尽,总结很好嗷
day15
讨论知识点
●今日是层序遍历比较简单,大家只需要记住队列一层一层基本没什么问题, 尽量不要用递归来写, 层序用队列可以比较好的模拟出一层一层的效果!
今日博客分享
博客内一共13种解法,覆盖所有遍历方式!二叉树的遍历是基础,大家一定要好好理解 各种方法都有实现!
打十个?我打了十几个! 很强!
day16
讨论知识点
●已经把递归的debug方法补充了,大家讨论东西不多,可以主要去看看怎么debug,会debug你可以写出来的算法题就可以写出来,因为你可以自己debug!
●
二叉树最大深度这题一个录友的解释很不错:你可以这么想,根节点3说你们左右节点去给我收集一下你们的最大高度报给我,左右子树的最大高度+根节点本身的高度(1)就是树的最大高度
然后左右子树一看,这也行,它两也分别给自己的左右子树去说,收集一下你们的最大高度哈
左子树9的左右子树一查,都是null。返回的都是0,左子树一合计,它的左右子树最大高度是0,加上左子树9的高度就是1了,报给根节点
右子树20也安排自己的左右子树去查一下最大高度,15和7就分别去查了,他们的情况和9是一样的,给他们的都是0,加上自身的高度才是1。将这两个结果个父节点20去比较,选出最大值是1,然后加上自身的高度就是2,把给根节点
根节点一看,一个1,一个2,选最大值2,然后加上自身的高度就是3,返回2,就是树的最大高度
●深度和高度:你就想现实中的树,每一片叶子都有自己的高度,这在日常生活中是显而易见的然后一般说深度都是说井,可以想一下新疆烤馕的那个馕坑烤包子,馕坑里面都是包子,每一个包子是不是都有自己的深度,肯定有个最深的,就是最大深度。没有或者这么一说
●
○这里的Java版本求深度不太一样,他都是求左右子树的left的深度,由于完全二叉树的叶子节点都是左倾的,当leftDepth==rightDepth时,左子树一定是满的,因为既然有元素存在与右子树,说明左子树一定是满的,但右子树不一定满,可以参考下面这张图,对应根节点的左子树的情况;如果leftDepth!=rightDepth,说明右子树的层数比左子树浅,也就是说右子树没到最深的那一层,那根据完全二叉树的定义右子树就一定是满的,对应如图根节点的情况。
○
今日博客分享
今天的题不少坑和奇思妙想 思路很好嗷,值得大家学习,代码风格和注释也真的是标准好看~ 题练千遍,其义自见 如题,该大佬用各种遍历方法完成了AC!
day17
讨论知识点
●递归的本质就是栈,因为递归也有递归栈(Java里面的虚拟机栈,元素就是每一个栈帧(也就是方法和他里面的元素构成的))
●递归考虑问题一般是考虑子问题扩展整体,也就是解决所有子问题就可以解决整体,所以可以先想象成最简单的二叉树也就是三个节点来尝试解决问题
●对于一些树递归问题, 大家首先是要确定递归方式, 前中后序的写法是不一样的, 需要获取子节点情况or子问题递归一般是考虑中序
●关于String+号和使用StringBuilder对程序性能的影响,大家可以看看这篇文章:
高效拼接字符串,你会用“+”还是StringBuilder.append?
●用不用回溯 取决于修改后的变量传入下一层函数后,本层函数还需不需要它了;是需要它改变后的值还是原值,一般要原值就回溯,要修改后的值通过定义函数返回值来得到
今日博客分享
回溯烧脑啊 思路清晰,注释完善,用python的朋友们如果觉得随想录的代码有些精简可以看这位大佬的~
day18
讨论知识点
●今天涉及了二叉树的构建,这边给小伙伴那的建议是一定先完全搞懂二叉树的前中后序遍历,然后一般是利用计算右子树节点数量来进行分割的,可以利用这一点总结成为一个模板哦!
●关于递归感觉还是很多同学没有理解透彻,这里我画一张图来帮助大家理解:
○
○附上一位同学看懂之后的感想:递归就是自己调用自己,然后一层一层返回,即将整个程序的运行空间安排在一个栈中。每当运行一个函数时,就在栈顶分配空间,函数退出后,释放这块空间。所以当前运行的函数一定在栈顶。嗯嗯,感觉之前是没有完全理解的,只是套着用,多谢多谢
今日博客分享
如果我说在今日刷题之前我完全不知道根据中序和后序如何构造一颗唯一的二叉树,你会觉得我很菜嘛呜呜呜 同感hh
day19
休息日
●大家没跟上进度的要赶上进度了哦! 赶上进度的人可以提前预习接下来的内容哈!
●没打卡的同学抓紧打卡了哈
day20
讨论知识点
●二叉搜索树->中序遍历搞定一切问题!!一定要利用这个特性!
●一个技巧:二叉搜索树自己设置一个pre节点+中序其实就相当于遍历一个有序链表了
●有同学问为什么很多题不用迭代做,其实大多数题都是用递归是最直观简单好写的,如果用迭代写本质上也是栈去模拟递归的过程,不是那么好写,所以大多数题掌握递归法就够可以了。除了最基本的前中后序遍历可以把迭代法学一下,其他的题目主要掌握递归就可以了,也是够面试用的了。
今日博客分享
逐渐烧脑了起来,果然还是我太菜呜呜呜 很认真,思路很清晰,问题都总结得很透彻!
day21
讨论知识点
●对于完全二叉树的问题解释:看一下完全二叉树的定义哈,左==右的话至少能保证左最深那一行可以满,否则右最深那一行也可以是满的,因为我们都是能左一直左,能右一直右来寻找的
●一位群友的解释也挺不错:1.我个人理解是因为完全二叉树的构造,所以单个节点的深度,一定是一直向下遍历左子树得到的。如果root的左子树深度,和root的右子树深度一样的话,说明root的左子树往下是个满二叉树2.如果左右两边深度不一致,那右子树一定是满二叉。如果有缺一个的,也只会在左子树
●大家遇到局部变量和全局变量设置的回溯的时候可以注意一下局部变量隐含回溯
●今日一个同学的提问:请问下这个前/后序和中序构造二叉树这题中,这两个代码中单层递归的边界范围考虑不太懂,为什么在前序的时候需要+1,后序的时候不需要?
○
○解答:上面的是依据中序和后序来构造,应该没问题,主要是下面的区别在于,下面是依据中序和前序来构造二叉树,+1是因为前序序列的第一个元素就是我们要在中序序列中找的分割点,+1就把它跳过去了嘛,它后面才是左右子树的内容。当然他们都遵顼的是左闭右开的原则。
今日博客分享
中序遍历秒了二叉搜索树,二叉树叫出祖先把我秒了 多样解法都有进行实现~
day22
讨论知识点
●今天突然有群友问动态规划了就回答一下之后要学的dp思路:
●1.动态规划主要就是多做题,理解子集->最优解的过程其实都是可以有证明过程的 2.把01背包,完全背包这种模型先学学,然后做类似的题,还有二维背包->一维的过程 3.用笔ordebug来模拟过程,放入元素为什么可以达到最优解,学一下卡哥的动规五步可以解决一些力扣上的问题,在深度的话就可以学yxc的子集->全集的y式dp分析法吧,主要还是多做题这个不太好讲,我大概是学了3个月才整明白了,还有你定义的i,j变量和推导要正确,dp就难在了公式推导这个过程学了模板后也得慢慢自己体会
今日博客分享
感觉比昨天简单一丢丢 一如既往的思路清晰,迭代递归解法都写啦
day23
讨论知识点
●遇到看不懂的方法的时候(指C++),可能是宏定义, 方法本身就是一个 宏定义,所以要找到定义他的地方,这种项目的代码 估计宏定义满天飞,如果没有好的文档,代码很难看
●只会写递归不会迭代的小伙伴注意:迭代法其实就是你把递归法看为栈的调用,把这个看不见的栈变成了看得见的栈的实现过程,里面操作都是差不多的!
●关于C++在【修剪二叉树】题目中,进行delete释放内存的问题:
○问题:
○代码加了内存释放,在运行时出错,[1,null,2] 这个输入,本地调试时,没有出错。卡哥的代码没有处理内存问题,难道这题不用自己释放内存?把delete的逻辑移除后,就通过了。手动delete反而会出错
○解答:因为最终答案是删除了原本的根节点,然后返回节点2作为新的根节点也就是答案,为此做了两个实验:1. 把right子树的指赋给原本的root,然后最终返回root,可以通过case;2. 把root指向right,然后之前用个tmp指向原本root的内存再删除,这次会报错。而报错的原因是释放的内存再次被使用,所以我猜测是LeetCode的判题机在判题的时候应该再次使用了原本子树根节点的那块内存导致的错误,你可以只删除那个会释放根节点的delete语句,其他的释放语句不去掉,结果还是可以通过的,所以你本地输出答案没有错误那说明就是lc自己的问题了,不用太过于纠结。
今日博客分享
数据结构与算法--二叉搜索树2(递归) 久违的求推荐博客,这位小伙伴把树形结构思路都写了出来还算很不错啦,如果能再多点收获,复杂度就更好了
最后一天二叉树了!深呼一口气 对搜索树的思考和总结很全面!
day24
讨论知识点
●大家力扣上建造用例的时候,对于树问题,可以尝试硬编码来进行构造数据哦如下图,还有就是利用力扣当中的playground来cv一下他们的工具,面试当中要求自己有建树操作,可以硬编码or力扣当中有给出String->TreeNode的方法
●
今日博客分享
今天没有求推荐的博客,大家打卡越来越少了鸭需要努力打卡的!!
day25
讨论知识点
●在昨天组合题目的时候, i+1和startindex+1的区别:startindex 在横向遍历的时候始终是1 这个题纵向遍历的位置要从横向下一个开始。 比如4 2 那个 ,第一次横向遍历第一个节点是1,下一层就需要从2开始。第二次横向遍历的节点是2下一层就要从3开始,你传入startindex ➕1还是2肯定不对啊。
●对于大家回溯问题的时候,Java传入的都是path的地址,所以需要new ArrayList(path) 这个相当于新创建了一个对象不然多少个都是数组
今日博客分享
今天没有求推荐的博客,大家打卡越来越少了鸭需要努力打卡的!!
day26
休息日
●大家没跟上进度的要赶上进度了哦! 赶上进度的人可以提前预习接下来的内容哈!
●没打卡的同学抓紧打卡了哈
day27
讨论知识点
●关于深拷贝和浅拷贝, 深拷贝是完全赋值一份对象, 地址不同, 大多数小伙伴在add答案的时候不知道为什么new 一个新的对象, 是因为如果不创建新对象, 我们放入多少个对象都是指向了path一个对象, 而浅拷贝呢 是地址一样, 也就是默认放进去的对象就是一个浅拷贝, 回溯的过程 会不断remove元素, 浅拷贝的对象会跟着变化因为地址一样, 所以大家得到的答案预期不一样, 可以根据这个来想一想回溯为什么需要深拷贝!
●对于debug 还是大家在自己不理解的地方, 预期不一样的地方之前打一下输出语句就可以了, 因为可能方法没完全理解等问题
●递归的过程就是解决子问题, 然后不断解决子问题来拓展成大问题, 昨天一位录友在树的问题体会出了这个点, 大家也可以好好想一下,构造个简单的7节点树体会一下
●关于回溯加减位置同学踩的坑(组合总和 II)
○
○加上sum不要那么早加,不然后面判重遇到continue跳到下一个循环就没有减掉,就重复加了。最好等到回溯前再加,前面判断就用sum + candidates[i] > target就行
今日博客分享
回溯还要多理解 lanyuan大佬一直坚持打卡,博客也是一如既往的高质量,很厉害! 代码随想录刷LeetCode | day27刷题回顾 图画的不错嗷~ 终于找到了一个以前一直没解决的Bug,最后一题用了动态规划的思想,牛刀小试 对于解题思路的思考很全面,关键问题都做了解答
day28
讨论知识点
●对于回溯的复杂度分析, 我们最简单的分析就是因为回溯取元素每个元素只有取or不取两种情况, 所以大家对回溯算法的时间复杂度理解,知道他是 指数级别的,大体是 2 的 n次方,其实就够了, 卡哥也写过一篇文章可以参考一下https://programmercarl.com/%E5%9B%9E%E6%BA%AF%E6%80%BB%E7%BB%93.html
●对于startIndex+ 1 和 i + 1的区别: 一个是下一次递归中 会从你start的一个数开始, 就无法保证一定是递增的这么一个效果, i+1的话可以保证递增答案的效果
●对于startIndex和used去重两种方法, 用的多的还是第二种哈, 因为第二种是比较通用的方法
●关于复原IP地址,Java解法二,有同学提出一个问题:
○
○问题:第四段是没有"."的,删第四段为什么不会删超出范围?
○要回答这个问题,我们首先要知道delete方法两个参数的意义
○start + number:是删除字符的起始点,start表示当前在原字符串的开始处理的位置,加上number是因为在stringBuilder中我们的字符串要比原字符串中多了number个".",number就是在此层递归之前stringBuilder已经加的"."的个数(不包括当前层加的".")。如下图,此时number应该为2。
○i + number + 2:其实可以拆分成 i + number + 1 + 1,前面的 i + number 其实和上面的同理,就是当前截取到的下标 i 要补上之前的 "." 的数量,然后第一个+1是因为我们要把此层递归的append的"."给删了,最后在+1是因为delete方法和其它很多方法一样,最后一个是开区间不包括的。
○
○所以delete方法就是把当层(number < 3)所append的内容给去掉,达到一个回溯的效果,那当层append 了哪些内容呢?如下图,也就是先是数字,还有最后面的点"."
○
○那么问题来了,这个delete方法就是针对的一般情况,也就是number < 3时,既加数字又加"."的情况,那么到第四个网段时,由于number == 3,我们是不会append最后一个"."的,那么delete方法最后不就越界了一位了吗?
○其实没关系的,看看StringBuilder的API文档,然后自己做个测试:
○
○可以看到其实尽管end超出了长度,那么delete就会尽力删到后面能删的地方为止,超出的就忽略了,也就是把end换成字符串的末尾,所以这里别说+2了,+100也没事,比如我下面写的测试例子:
○
○而越界发送的错误StringIndexOutOfBoundsException主要针对start为负数,或者超过了长度,或者比end要大的情况才抛出,与end超出长度无关的。
○所以这个例子告诉我们,遇到问题涉及了不熟悉的API,我们最好要去查一下官方的API文档,然后自己再写个小test,很多问题其实也就迎刃而解了。
今日博客分享
每个章节前面的几道题都是基础和核心,一定要理解透彻,后面做题就会越来越顺 所言极是呀!
day29
讨论知识点
●子序列问题 类似 子集问题,子集问题不需要加return, 可以看一下卡哥的文章,本质原因 是 全排列 组合 组合总和 分割问题 都是在 叶子上去结果,子集问题,子序列 都是在 树的节点上取结果
●used数组和set没有本质的区别, 数组效率会高一些, 还是建议大家用数组的, 面试的时候数组也比较好写一些哈, 当然还需要注意下标的映射问题
●关于Python里,为什么二维数组 append一维列表 path[:] 和 path 结果不一样呢?
○这其实是语言的特性,我们写一下测试例子就知道了
○
○一个是引用,一个是拷贝数据进去,前者会受到原数组改变的影响,后者则不会
●组合和子集问题 只要可以排序 就也能不要used数组达到去重 排列问题的话 就一定需要额外的数组来记录下 很相像的 所以说需要自己总结下 选一个适合自己的模板来写
●用used去重或者不用used直接通过index去重都是可以的,只不过是两种不同的实现方式,关键是要理解深度去重和广度去重的不同之处,清楚代码运行在哪里是在树枝上哪里是在树层上。
今日博客分享
无论组合还是排列,去重都是重点 博客中对组合去重思考很深入,为什么组合去重必须排序?值得一看!
day30
讨论知识点
●回溯算法与dfs的区别:所有的回溯算法都可以说是 深搜,所有的深搜 都可以说是 递归。 那么回溯算法其实就是更具体的一个分类, 也就是父类和子类的一个关系
●还是有同学没分清除浅拷贝和深拷贝: 浅拷贝是操作同一个对象, 深拷贝是复制一个一模一样的地址不一样的对象!!!牢记, add要new一个新的
●今天有同学问到:什么时候用回溯什么时候用dfs?
○回溯其实是dfs的增强版了,你发现回溯里面不也是在dfs吗?只是多了一个“撤销”的过程,本质都是在递归。所以问题就在于什么时候需要撤销之前的操作,回溯的本质其实就是暴力,就是通过这个递归的过程去尝试所有的情况,只不过我们可以通过剪枝去一定程度优化。所以像分割问题、组合问题、排列问题这种需要“尝试”所有可能情况、所有位置情况的场景可以优先考虑回溯,也就是需要撤销重试的操作。至于纯dfs其实就是之前刷“树”的专题时会用到的,题目一般会明确指出需要在操作题目给出的树这个数据结构来得出答案的场景。然后你会发现回溯过程中往往也会隐藏地生成一棵树的结构,卡哥题解中画的图就经常出现,所以也印证了我前面说的回溯本质是“增强版”的dfs这个结论。其实就看你需不需要“撤销重试”这么一个过程了,回溯和dfs本质都是递归,然后我们根据具体场景去额外添加一些操作来解答题目,就是看在每层递归过程中需要进行处理。
○说起解题技巧,我想起一个比较好的经验给大家分享下。之前在卡哥的知识星球里看一位大佬分享的:就是解题能力,其实可以看作是一种“抽象能力”,就是把题目中的外衣去除,看到其本质场景,然后由场景就可以根据经验知道最合适的解题算法了,这样大致的思路就对了,剩下的就是细节的处理。这点我也是深有体会,今年秋招做oppo、深信服笔试的时候,比较简单的就是斐波那契,套个皮,什么兔子跳青蛙跳的,其实本质就那样,包括大家做过的爬楼梯;笔试公认最难之一的网易,很多都是很复杂很长的题干,但是大部分可以抽象出矩阵操作的场景(当然细节也比较难);还有很多你尽管没有最优解思路,大部分也可以抽象成回溯+剪枝来拿到一定的分数。所以说用不用回溯,可以看你抽象出来后的场景属不属于回溯可以用的场景(比如分割、组合、排列场景)。希望这个经验对大家有所启发吧。如果想看到更多大佬分享和干货也可以进卡哥的知识星球看看,也有不少优质资源。
●为什么组合总和2这道题,用491递增子序列里讲的去重方法,还是会出现重复呢? 这是一个很好的问题,如果直接像递增子序列中那样用 set 对组合进行去重,会发现 set 只能对同一树层上的元素进行去重,一个简单例子如:[2,1,2],target = 3;其无法保证相同的数字会在同层出现,而每次递归传入的 i+1来保证不往回走也失去了意义。这样来看,组合的去重,进行排序是必须的。为什么递增子序列里不需要排序直接用set去重呢?引用lanyuan同学的解答 : "题里要求的“递增”,其实就是限制了同一树层中出现的数字都是有序的。即,实际可以选取到的数字,是有序的。所以我们依然可以在遍历的同时去重。"
今日博客分享
今天没有求推荐的博客,大家打卡越来越少了鸭需要努力打卡的!!
day31
讨论知识点
●关于摆动序列为什么pre=cur要放在if当中:例子1,2,2,3, 他这个摆动是一上一下, 要是没满足在2,2这种地方更新, pre直接变成0了这肯定是不行的, 前面比如1你中间不要变成0 1,2,2,3本来是1,0,1这么一个差应该答案是2, 但是你一更新那个pre变成0那不就是没初始化过么就错了,我们设置了pre==0是没初始化的情况
●关于c的&, 建议大家好好看一下c中&的用法, 加了跟没加主要就是方法内部是否会改变本身, 也就是引用地址
今日博客分享
开始贪心了,感觉很难想到 如果没见过同类型的,有些贪心问题确实是很难想鸭
day32
讨论知识点
●关于c++大家还是搞清楚迭代器和一些语法的知识, 经常提醒大家语法牢固刷题才能更好, 希望大家起码掌握好自己的编程语言吧
●四数之和中, 我们j > i + 1等后面一系列操作不会导致一直跳过的, 至少会取4个数!
●关于55跳跃游戏问题:这里直接是cover = i + nums[i],不可以吗,直接跳跃到最大值坐标?
○
○因为有可能你当前这一格只能跳一步,但是你前一格可以跳10步,cover意思是当前能覆盖的最远的范围,所以要一直取最大的那个
今日博客分享
15分钟单杀了<跳跃游戏 II> 可以夸夸我吗 每道题都列出自己的代码和卡哥代码进行分析比对,对提高代码技巧理清思路很有帮助!
day33
休息日
●大家没跟上进度的要赶上进度了哦! 赶上进度的人可以提前预习接下来的内容哈!
●没打卡的同学抓紧打卡了哈
day34
讨论知识点
●对于摆动序列的题目, 为什么prediff不是每次都要更新成curdiff的解释:样例1,2,2,3,这个摆动是一上一下, 要是没满足在2,2这种地方更新, pre直接变成0了这肯定是不行的, 前面比如1你中间不要变成0。1,2,2,3本来是1,0,1这么一个差应该答案是2, 但是你一更新那个pre变成0那不就是没初始化过么就错了,我们设置了pre==0是没初始化的情况
●对于分糖果题目录友理解:就是如果不这样操作的话,就是没法保证第i个小孩的糖果数量既大于左边的也大于右边的。只取candyVec[i + 1] 的话,第一次从前到后遍历得到的数值可能会被改变。
●134加油站:为什么是从后往前遍历呢?
○
○结合本题贪心方法二里的描述的思想,因为本题说了如果有解一定会有一个唯一答案对吧,说明总加油量一定是大于总消耗量的,只是不均匀,可能出现前面不足但是后面又比较多补上了情况,所以这里前面我们已经从前往后发现不能走得通,说明从前面的加油站,至少是从0号加油站开始,是行不通的,那么前面不足的后面必有补充(因为有唯一答案),所以是从后面开始遍历的,发现第一个可以填补汽油负数结余值的就是答案
今日博客分享
第一题自己能想到,第二题有些难,第三题很巧妙 加油站的思路讲解很棒 脚踏实地,不可顾此失彼
day35
讨论知识点
●对于topK问题的大堆和小堆: 大顶堆是把所有的元素放进去不用考虑poll, 因为你poll也是当前最大不是全局最大, 小顶堆是我们维护一个k大小的堆, 每次出最小的, 最后剩下来的就是k个大的要考虑poll 一个复杂度是NlogN, 一个复杂度是NlogK
●为什么树的迭代不能用队列: 因为迭代的本质是在循环中完成了递归的过程, 递归的本质是栈, 故需要用栈模拟
●提醒大家Java比较大小的时候最好还是用 Integer.compare(a, b), 否则有可能溢出
今日博客分享
第二题比较难想到
day36
讨论知识点
●无重叠区间这道题 count为什么初始化为1?count记录的是非交叉的个数,前面也判断过intervals.size()==0的情况,往下就是>0最少是1
今日博客分享
深入理解区间问题 总结可以说是很全面啦! 推荐参考!
day37
讨论知识点
●对于股票带手续费那题的MIN 赋值问题:例子1,3,5,7,10,3,手续费3:这边解释一下就是, 我们一开始考虑的因素是, 只要有获利就卖掉, 但是这边可能出现一种情况就是, 可能前面的及时能获利, 但是不卖掉再最后卖掉可能获利更多, 考虑这个因素我们在第一个if内MIN=price[i]-fee, 这样赋值可以保证如果后面有出现更大的获利, 不用减去两次手续费导致结果错误。那么按照我生成的这个例子的话就是如果你按照MIN=price[i]付费, 我们会选择1买入7卖出, 5买入10卖出,扣两次手续费赚了5块钱, 而考虑MIN=price[i]的时候他虽然还是在7卖出了, 但是考虑我们可以不卖所以7这个地方可以变成4的买入价(这样后面如果有低的会重新赋值, 如果有高的话避免二次手续费的扣除), 可以看出这种算法可以保证1买入10卖出, 赚了6块钱。
●下面是另一位录友的解释
●
●遇到不会的问题, 想要测试样例, 可以先提交获取几个样例, 有想法就落地进行对照试验, 对照debug来进行测试, 提高自己
今日博客分享
今天没有求推荐的博客,大家打卡越来越少了鸭需要努力打卡的!!
day38
讨论知识点
●break 结束的 是for循环, return是结束当前递归返回
●对于最小花费爬楼梯的题, 顶部就是n, n - 1的位置不管跳1or2, 都是到n
今日博客分享
算法训练Day38 | 动态规划理论基础;LeetCode509. 斐波那契数;70. 爬楼梯;746. 使用最小花费爬楼梯 这个小伙伴的博客写的非常非常棒大家可以去学习!!!各方面都很棒!
day39
讨论知识点
●c++中不加&会复制一份数组,加了是引用不用新建一个数组
●1.动态规划主要就是多做题,理解子集->最优解的过程其实都是可以有证明过程的 2.把01背包,完全背包这种模型先学学,然后做类似的题,还有二维背包->一维的过程 3.用笔ordebug来模拟过程,放入元素为什么可以达到最优解,学一下卡哥的动规五步可以解决一些力扣上的问题,在深度的话就可以学yxc的子集->全集的y式dp分析法吧,主要还是多做题这个不太好讲,我大概是学了3个月才整明白了,还有你定义的i,j变量和推导要正确,dp就难在了公式推导这个过程学了模板后也得慢慢自己体会
●局部变量回溯, 是隐含的回溯, 全局变量的回溯是显示的回溯, 对于什么题目该选择什么回溯方法, 我建议能用全局就用全局, 隐含回溯得创建销毁还麻烦, 当然全局和局部大多数情况是可以互相转化的
今日博客分享
算法训练Day39 | LeetCode62. 不同路径;LeetCode63.不同路径II这个小伙伴的博客写的非常非常棒大家可以去学习!!!各方面都很棒!
day40
休息日
●大家没跟上进度的要赶上进度了哦! 赶上进度的人可以提前预习接下来的内容哈!
●没打卡的同学抓紧打卡了哈
day41
讨论知识点
●Java当中栈有很多实现方式, LinkedList, ArrayDeque, 数组都可以模拟栈, 所以其实他们的本质都是栈, 实现不一样而已, 其他语言同理有很多能实现的
●合并二叉树的时候是直接考虑合并的, 不需要管排列
●补充了排序算法, 大家可以看一下
●关于Java中,基本类型比如int的数组,我们用Arrays.sort() 方法进行排序时,是不支持用lambda或者Comparator去自定义比较器的,它们只支持引用类型,不支持基本数据类型。解决办法:转化为List、使用包装类数组、IntStream等。
今日博客分享
算法训练 Day41 | 动态规划训练Day3;LeetCode343. 整数拆分;LeetCode96. 不同的二叉搜索树这个小伙伴的博客写的非常非常棒大家可以去学习!!!各方面都很棒!
day42
讨论知识点
●怎么确定这个题的解可以用01背包的方式来解呢:多个物品, 有容量限制, 选or不选
●c++在打比赛的时候有的时候会卡常数,有时候vector过不了数组能过
●今天有同学提问:01背包有个地方不太懂:dp[i - 1][j - weight[i]] + value[i]这里,为什么是用j - weight[i]来表示不放物品i的最大价值?不放物品i时的背包容量不一定是j - weight[i]啊,可能是小于这个数
○回答:dp本身的含义就包含了最优,也就是说j-weight也包含了比它小的重量中所有情况中最优的那一种
今日博客分享
今天没有求推荐的博客,大家打卡越来越少了鸭需要努力打卡的!!
day43
讨论知识点
●一维优化不能先遍历容量的原因:主要是 一维的话 上一层的状态没法保存,已经被本层更新了
●01背包二维数组转一维数组:我个人认为应该是和初始化有关,因为是dp i 是和i-1相关,所以正序的话相当于一直在叠加前一项,如果反过来倒序的话,每个前面都是初始化的0所以没有叠加问题(录友理解)
今日博客分享
今天没有求推荐的博客,大家打卡越来越少了鸭需要努力打卡的!!
day44
讨论知识点
●有序数组转为二叉树-> 二分数组可以实现跟平衡树差不多的自平衡操作
●完全背包求排列数和求组合数我有一点想不明白,求排列数的时间复杂度应该比求组合数的时间复杂度要高吧?为什么体现在代码层面上却是一样的呢?-> 卡哥回答:求排列和求组合 其实是一样的, 你想一下 刚刚做过的 回溯算法中,求排列和求组合的区别。
今日博客分享
今天没有求推荐的博客,大家打卡越来越少了鸭需要努力打卡的!!
day45
讨论知识点
●有的时候大家会发现debug并不能找到问题, 这其实往往问题会出现在返回值和函数调用的过程, 这种时候就只能拆分的粒度更细一点或者单独test一下函数调用
●递归的时候一般只需要考虑子问题, 子问题处理没错一般就能默认处理完主问题
●组合排列题时,怎么好直接判断该用回溯还是dp呢?
○回溯是可以把具体的集合都列出来的, dp只能求有几种这样的集合,比如说377. 组合总和 Ⅳ,最后要求的就是输出种类数而不是所有组合都列出来,所以用的是dp而不需要回溯。
今日博客分享
今天没有求推荐的博客,大家打卡越来越少了鸭需要努力打卡的!!
day46
讨论知识点
●背包问题为什么初始化的时候要弄一个背包容量为0的情况:我的理解是递推公式是从前推倒后面的,前面的赋值了,后面的才能进行,有些题目用二维数组的情况下,i=0 或者j=0的时候,dpi也是有实际值和实际意义的,很多时候不是初始化的零
今日博客分享
今天没有求推荐的博客,大家打卡越来越少了鸭需要努力打卡的!!
day47
休息日
●大家没跟上进度的要赶上进度了哦! 赶上进度的人可以提前预习接下来的内容哈!
●没打卡的同学抓紧打卡了哈
day48
讨论知识点
●打劫问题为什么dp[i]不偷可以直接为dp[i-1]呢:因为我们确定不偷第i个 所以我们的范围从0~i变成了0~i-1 所以dp[i] = dp[i-1],如果偷第i个,那么第i-1个就不能偷,那我们的范围变成0~i-2,同时要加上第i个的钱数 所以dp[i] = dp[i-2] + nums[i]
●整数拆分这一题,为什么递推公式不是dp[i]=max((i - j) * j, dp[i - j] * j)呀? 为什么还要跟dp[i]本身比较一下:因为 i固定,j在遍历,我们要选一个最大的 dp[i]
今日博客分享
今天没有求推荐的博客,大家打卡越来越少了鸭需要努力打卡的!!
day49
讨论知识点
●对于ip回溯, 我们要掌握好回溯的粒度, 是回溯数字 , 回溯点, 还是回溯整体, 分清楚即可
今日博客分享
今天没有求推荐的博客,大家打卡越来越少了鸭需要努力打卡的!!
day50
讨论知识点
●123题为什么最后不是比较第一次卖出和第二次卖出哪个大,而是直接选择了第二次卖出的?:因为第二次一定是大于等于第一次的,最简单的例子就是比如我们第一次卖出后,在同一天再次买入卖出,就是等于第一次,这样就是两次了
●股票问题最重要的就是分清楚, 重复买入卖出, 买入卖出的定义状态, 怎么转移, 可以从子问题推到, 举最简单的两三天来进行test即可
●今日提问:想问问今天股票的IV,这个2*k-1的“-1"有啥含义吗?是不是说,停止遍历的位置是在上次的卖出?如果是<2*k的话停止是在这一次的买入?虽然最后的+=2都会直接跳过
○
○小于2k-1,那么最大就是到2k-2,每次循环计算买入和卖出两种状态,那可达最大下标就是2k了,也就是第k次卖出,包含了所有情况了
今日博客分享
今天没有求推荐的博客,大家打卡越来越少了鸭需要努力打卡的!!
day51
讨论知识点
●为什么字符需要-'a','A',数字需要见-'0'主要是为了映射在数组上面, 不然都是ascii码映射就不准确了, 也无法定位
●再次重复一下这个问题:“如果直接写 list.add(path),因为path为一个引用类型,即内存中只有一份,那么每一次list所add的path都是取得同一个path,即后面path的每一个改变均会对list.add(path)中的path有影响(会导致最终每次存入的path都是同一个值)”
●714.买卖股票的最佳时机含手续费,有同学提问:dp[0][1]是不是应该为-fee?
○第0天如果不持有股票,可以看成两种情况:1. 买入再卖出 2. 不交易。在不带手续费的题目中两种其实没有区别,没亏也赚,但是带了手续费你买入再卖出肯定就亏了手续费,而不交易你就是0,max(-fee, 0)当然选择后者
今日博客分享
今天没有求推荐的博客,大家打卡越来越少了鸭需要努力打卡的!!
day52
讨论知识点
●子序列问题, 一般都是定义一个n数组, 然后用最小子问题来考虑dp方程, 最简单的就比如最长子序列是, 当前如何最长, 保证最长即dp方程dp[i]=max(dp[i],dp[j] + 1), 这种都是通过子集合推的, 其实dp问题都考虑子集合如何推大集合即可
今日博客分享
今天没有求推荐的博客,大家打卡越来越少了鸭需要努力打卡的!!
day53
讨论知识点
●dp数组的长度都是怎么决定呢?有时看到是len,还有时候是len+1?这个主要看0有无意义和你想怎么定义, 都定义成len+1也没关系不缺那一个内存, 一般竞赛选手都是定义大数组所以内存一般没那么关键
●请问我要什么时候用一维数组什么时候用二维数组呢?串匹配和矩阵一般二维, 其他的看模型, 还是得多做题熟悉一下
今日博客分享
今天没有求推荐的博客,大家打卡越来越少了鸭需要努力打卡的!!
day54
休息日
●大家没跟上进度的要赶上进度了哦! 赶上进度的人可以提前预习接下来的内容哈!
●没打卡的同学抓紧打卡了哈
day55
讨论知识点
●Gas Station这题,有没有存在这么个情况,sum(gas) > sum(cost),但在某个站剩余的油量不够跑到下一站的Case? 文中说如果总油量减去总消耗大于等于零那么一定可以跑完一圈?答:这个情况对于没选好站是存在的,但是选好站一定可以跑完, 因为我们选好起点的话只要你一整圈能正, 最优解小圈肯定正
●115.不同的子序列:不用s[i - 1]来匹配,个数为dp[i - 1][j]。为什么是j
○
○看那个例子,s是bagg,t是bag时,i是4,j是3,s[i-1]和t[j-1]相等。匹配的情况是s[0]s[1]s[3]组成的bag,不匹配的情况是s[0]s[1]s[2]组成的bag。看不匹配的情况,和s是bag,t是bag时一样,这时i是3,j还是3,j没变。匹配的情况已经保证最后的g相等了,只要s里有ba,t是ba就行了。
○不使用s[i-1],而我们这里要计算的是dp[i][j],那就是要是匹配到t[j-1]结尾,根据下面的例子中bagg我们可以用前三个字母就组成了bag,也就是我们想要的目标,那就是dp[i-1][j],意思是以i-2为结尾的s子序列中出现以j-1为结尾的t的个数,通俗的理解为:不需要第i-1个字符也可以凑出以j-1结尾的目标子序列
今日博客分享
今天没有求推荐的博客,大家打卡越来越少了鸭需要努力打卡的!!
day56
讨论知识点
●编辑距离dp解释:dpi - 1 word1 剪一个元素,就是 dpi - 1 + 1,dpi word2 剪一个元素 就是 dpi - 1 + 1, 如果实在理解不了就 不用简化的公式,直接 dpi = min({dpi - 1 + 2, dpi - 1 + 1, dpi + 1}); , 也没问题
●分糖果:其实这题就是你直接看成幼儿园问题, 大家一人一个, 从左到右哪个小朋友高多给一个, 从右到左再来一遍就行, 你这个先左开还是先右开顺序无所谓但是至少要两遍,你不能两遍同方向那没有意义
今日博客分享
今天没有求推荐的博客,大家打卡越来越少了鸭需要努力打卡的!!
day57
讨论知识点
●回文子串主要是靠一个简单模板, 也就是二重循环for(int i = n - 1; i >= 0; i --) for(int j = i; j < n; j ++) 来嵌套, 然后根据二重循环来进行回文串判断, 其实也就是判断相等逻辑, 然后根据需求来进行即可
今日博客分享
今天没有求推荐的博客,大家打卡越来越少了鸭需要努力打卡的!!
day58
讨论知识点
●只要能实现栈的都可以实现单调栈!
●单调栈主要就是维护需要值的单调性, 通常是前面的值需要后面的值来进行判断
今日博客分享
今天没有求推荐的博客,大家打卡越来越少了鸭需要努力打卡的!!
day59
讨论知识点
●接雨水问题, 也可以利用双指针, 大家可以把接雨水想象成一个凹凸不平的泳池, 然后我们往里面蓄水, 每一个单元格能蓄水的最大量取决于他左右两边(整体)的最大值的(左右值都取最大后取最小)
今日博客分享
今天没有求推荐的博客,大家打卡越来越少了鸭需要努力打卡的!!