├── .DS_Store ├── pics ├── 公众号.png ├── 知识星球.png ├── 算法大纲.png ├── 阿里云.png ├── .DS_Store ├── 公众号二维码.jpg └── 微信搜一搜.png └── problems ├── 前序 ├── Java处理输入输出.md ├── 编程素养部分的吹毛求疵.md ├── 成都互联网公司总结.md ├── 深圳互联网公司总结.md ├── 杭州互联网公司总结.md ├── 广州互联网公司总结.md ├── 力扣上的代码想在本地编译运行?.md ├── 关于空间复杂度,可能有几个疑问?.md ├── vim.md ├── 北京互联网公司总结.md ├── 什么是核心代码模式,什么又是ACM模式?.md ├── 上海互联网公司总结.md └── 程序员写文档工具.md ├── 其他 └── 参与本项目.md ├── 0160.相交链表.md ├── 知识星球精选 ├── 刷力扣用不用库函数.md ├── 技术不好如何选择技术方向.md ├── 不喜欢写代码怎么办.md ├── 要不要考研.md ├── 合适自己的就是最好的.md ├── 面试中发散性问题.md ├── 如何权衡实习与秋招复习.md ├── HR特意刁难非科班.md ├── 初入大三选择考研VS工作.md ├── 提前批已经开始了.md ├── 非科班的困扰.md ├── 逼签.md ├── 英语到底重不重要.md ├── 秋招的上半场.md ├── 入职后担心代码能力跟不上.md ├── 博士转行计算机.md ├── 秋招进行中的迷茫与焦虑.md ├── 大厂新人培养体系.md ├── 关于提前批的一些建议.md ├── 秋招开奖.md ├── 备战2022届秋招.md ├── 刷题攻略要刷两遍.md ├── 专业技能可以这么写.md ├── 天下乌鸦一般黑.md ├── 不少录友想放弃秋招.md ├── 不一样的七夕.md ├── 秋招总结2.md ├── 客三消.md ├── HR面注意事项.md ├── 关于实习大家的疑问.md ├── 写简历的一些问题.md ├── offer对比-决赛圈.md ├── 秋招下半场依然没offer.md ├── offer总决赛,何去何从.md ├── 秋招总结3.md └── 非科班2021秋招总结.md ├── 面试题 02.07. 解法更新.md ├── 贪心算法理论基础.md ├── 周总结 ├── 20201203贪心周末总结.md ├── 20201217贪心周末总结.md ├── 20201112回溯周末总结.md ├── 20201010二叉树周末总结.md ├── 20201224贪心周末总结.md ├── 20201126贪心周末总结.md ├── 20210128动规周末总结.md ├── 20201210复杂度分析周末总结.md ├── 20201017二叉树周末总结.md ├── 20201030回溯周末总结.md ├── 20210107动规周末总结.md ├── 20210121动规周末总结.md └── 20210114动规周末总结.md ├── 栈与队列理论基础.md ├── 链表总结篇.md ├── 1221.分割平衡字符串.md ├── 数组理论基础.md ├── 双指针总结.md ├── 0141.环形链表.md ├── 动态规划理论基础.md ├── 背包总结篇.md ├── 数组总结篇.md ├── 0283.移动零.md ├── 0189.旋转数组.md ├── 字符串总结.md ├── 0724.寻找数组的中心索引.md ├── 0657.机器人能否返回原点.md ├── 0055.跳跃游戏.md ├── 回溯算法理论基础.md ├── 哈希表总结.md └── 哈希表理论基础.md /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDBSK/code-suixianglu/HEAD/.DS_Store -------------------------------------------------------------------------------- /pics/公众号.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDBSK/code-suixianglu/HEAD/pics/公众号.png -------------------------------------------------------------------------------- /pics/知识星球.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDBSK/code-suixianglu/HEAD/pics/知识星球.png -------------------------------------------------------------------------------- /pics/算法大纲.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDBSK/code-suixianglu/HEAD/pics/算法大纲.png -------------------------------------------------------------------------------- /pics/阿里云.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDBSK/code-suixianglu/HEAD/pics/阿里云.png -------------------------------------------------------------------------------- /pics/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDBSK/code-suixianglu/HEAD/pics/.DS_Store -------------------------------------------------------------------------------- /pics/公众号二维码.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDBSK/code-suixianglu/HEAD/pics/公众号二维码.jpg -------------------------------------------------------------------------------- /pics/微信搜一搜.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDBSK/code-suixianglu/HEAD/pics/微信搜一搜.png -------------------------------------------------------------------------------- /problems/前序/Java处理输入输出.md: -------------------------------------------------------------------------------- 1 | 在面试中,我们常常会遇到面试官让我们用某种编程语言做题,并要求能够在本地编译运行。 2 | 这种模式也被称做ACM模式。 3 | 4 | 本文将介绍如何用Java处理输入输出。 5 | 6 | -------------------------------------------------------------------------------- /problems/其他/参与本项目.md: -------------------------------------------------------------------------------- 1 | 2 | 优化已有代码 3 | ![](https://code-thinking-1253855093.file.myqcloud.com/pics/20210821161813.png) 4 | 5 | **push代码之前 一定要 先pull最新代码**,否则提交的pr可能会有删除其他录友代码的操作。 6 | 7 | 一个pr 不要修改过多文件,因为一旦有一个 文件修改有问题,就不能合入,影响其他文件的合入了。 8 | 9 | git add之前,要git diff 查看一下,本次提交所修改的代码是不是 自己修改的,是否 误删,或者误加的文件。 10 | 11 | 提交代码,不要使用git push -f 这种命令,要足够了解 -f 意味着什么。 12 | 13 | 14 | 不用非要写出牛逼的代码才能提交PR,只要发现 文章中有任何问题,或者错别字,都欢迎提交PR,成为contributor。 15 | ![](https://code-thinking-1253855093.file.myqcloud.com/pics/20210927113149.png) 16 | -------------------------------------------------------------------------------- /problems/0160.相交链表.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 |

参与本项目,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!

6 | 7 | 同:[链表:链表相交](https://programmercarl.com/面试题02.07.链表相交.html) 8 | ----------------------- 9 |
10 | -------------------------------------------------------------------------------- /problems/前序/编程素养部分的吹毛求疵.md: -------------------------------------------------------------------------------- 1 | ## 代码风格 2 | 3 | - `不甚了解`是不能更了解的意思,这个地方应该使用存疑。 4 | - `后期在不断优化`,'在'应为'再'。 5 | - `googlec++编程规范`,Google拼写错误 6 | 7 | ## 代码本地编译 8 | 9 | - `粘到本例来运行`存疑,应为本地 10 | - `本题运行`存疑,应为本地 11 | 12 | ## ACM二叉树 13 | 14 | - 左孩子和右孩子的下标不太好理解。我给出证明过程: 15 | 16 | 如果父节点在第$k$层,第$m,m \in [0,2^k]$个节点,则其左孩子所在的位置必然为$k+1$层,第$2*(m-1)+1$个节点。 17 | 18 | - 计算父节点在数组中的索引: 19 | $$ 20 | index_{father}=(\sum_{i=0}^{i=k-1}2^i)+m-1=2^k-1+m-1 21 | $$ 22 | 23 | - 计算左子节点在数组的索引: 24 | $$ 25 | index_{left}=(\sum_{i=0}^{i=k}2^i)+2*m-1-1=2^{k+1}+2m-3 26 | $$ 27 | 28 | - 故左孩子的下表为$index_{left}=index_{father}\times2+1$,同理可得到右子孩子的索引关系。也可以直接在左子孩子的基础上`+1`。 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /problems/知识星球精选/刷力扣用不用库函数.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 | 6 | # 究竟什么时候用库函数,什么时候要自己实现 7 | 8 | 在[知识星球](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ)里有录友问我,刷题究竟要不要用库函数? 刷题的时候总是禁不住库函数的诱惑,如果都不用库函数一些题目做起来还很麻烦。 9 | 10 | 估计不少录友都有这个困惑,我来说一说对于库函数的使用。 11 | 12 | 一些同学可能比较喜欢看力扣上直接调用库函数的评论和题解,**其实我感觉娱乐一下还是可以的,但千万别当真,别沉迷!** 13 | 14 | 例如:[字符串:151. 翻转字符串里的单词](https://mp.weixin.qq.com/s/X3qpi2v5RSp08mO-W5Vicw)这道题目本身是综合考察同学们对字符串的处理能力,如果 split + reverse的话,那就失去了题目的意义了。 15 | 16 | 有的同学可能不屑于实现这么简单的功能,直接调库函数完事,把字符串分成一个个单词,一想就是那么一回事,多简单。 17 | 18 | 相信我,很多面试题都是一想很简单,实现起来一堆问题。 所以刷力扣本来就是为面试,也为了提高自己的代码能力,扎实一点没坏处。 19 | 20 | **那么平时写算法题目就全都不用库函数了么?** 21 | 22 | 当然也不是,这里我给大家提供一个标准。 23 | 24 | **如果题目关键的部分直接用库函数就可以解决,建议不要使用库函数**。 25 | 26 | **如果库函数仅仅是 解题过程中的一小部分,并且你已经很清楚这个库函数的内部实现原理的话,那么直接用库函数。** 27 | 28 | 使用库函数最大的忌讳就是不知道这个库函数怎么实现的,也不知道其时间复杂度,上来就用,这样写出来的算法,时间复杂度自己都掌握不好的。 29 | 30 | 例如for循环里套一个字符串的insert,erase之类的操作,你说时间复杂度是多少呢,很明显是$O(n^2)$的时间复杂度了。 31 | 32 | 在刷题的时候本着我说的标准来使用库函数,详细对大家回有所帮助! 33 | 34 | 35 | -------------------------------------------------------------------------------- /problems/知识星球精选/技术不好如何选择技术方向.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 | 6 | # 技术不太好,也不知道对技术有没有兴趣,我该怎么选? 7 | 8 | 最近在[知识星球](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ)里解答了不少录友们的疑惑,其实发现一个挺普遍的问题: 9 | 10 | * 我技术很一般 11 | * 对技术也没有什么追求 12 | * 要是对什么岗位感兴趣我也不知道 13 | * 以后自己喜欢干什么也不太清楚 14 | 15 | **相信说到了不少录友心里去了, 其实目前应试教育下 确实很难找到自己感兴趣的事情**。 16 | 17 | 但我想说的是,并不是技术不好就什么都做不了,依然有很多选择,只不过录友们没有接触过,所以就不知道自己接下来要往哪个方向走。 18 | 19 | 这里我给出一些路线,大家可以参考: 20 | 21 | 方向一:走纯研发路线,去大厂,如果真的对技术提不上兴趣可能会走的很辛苦。 22 | 23 | 方向二:如果技术还凑合,不做纯研发,退一步也可以考虑去大厂做测试相关的工作,对技术要求没有那么高,但也需要技术能力,而且技术能力越强越吃香。 24 | 25 | 方向三:去银行,证券,国企类的企业去做研发岗位,这种国有企业的技术面试相对简单不少,比较轻松,还很稳定,收入虽说不高,但生活足够滋润。 26 | 27 | 方向四:做toC(面向普通用户)的产品经理,toC产品经理这个岗位就特别卷,因为这个岗位门槛太低了,任何专业的同学都可以去做产品经理。 这样自己所学的技术就基本没有用了,也凸显不出技术上的优势,但如果自己真的对APP之类的各种应用得心应手,优点缺点,用户爽点、日活、次留等等手到擒来,倒可以试一试。 28 | 29 | 方向五:做toB的产品经理,包括云计算,大数据这些产品都是需要产品经理的,例如百度云,腾讯云,阿里云等等,这种产品本身就是技术产品,所以需要懂技术的产品经理来做设计,即需要产品的抓住需求的能力,也需要懂点技术,既可以发挥自己的技术能力,还可以做产品规划,基本也不用写代码。 30 | 31 | 对技术要求不高的岗位也挺多的,发展也很好,只要大家多去了解,总会找打符合自己的岗位。 32 | 33 | -------------------------------------------------------------------------------- /problems/知识星球精选/不喜欢写代码怎么办.md: -------------------------------------------------------------------------------- 1 | 2 | # 看到代码就抵触!怎么办? 3 | 4 | 最近在[知识星球](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ)里,看到了不少录友,其实是不喜欢写代码,看到 哪些八股文都是很抵触的。 5 | 6 | 其实是一个普遍现象,我在星球里分享了一下,我对这一情况的一些想法。 7 | 8 | 发表在星球里,很快就有了60多个赞,也确实说道大家的心里去了。 9 | 10 | ![](https://code-thinking-1253855093.file.myqcloud.com/pics/20211019222938.png) 11 | 12 | 我在这里再给公众号的录友们也分享一下: 13 | 14 | 很多同学不喜欢计算机,也不喜欢写代码,看到各种大堆的面经 八股文,心里是十分抗拒的。 15 | 16 | 所以总是拿一些其他的事情来拖延,最后发现秋招或者春招 完全拖过去了,或者说等求职的时候发现自己完全没有达到应聘的水平,再陷入 深深的焦虑之中。 17 | 18 | 这里有一个很重要的问题,就是**当你发现你不喜欢计算机的时候,那问问自己喜欢什么呢?** 19 | 20 | 如果喜欢看电影,逛街,打游戏,甚至格调再高一点 喜欢画画,喜欢音乐,唱歌之类的,这些爱好如果没有达到专业的程度,那么仅仅是日常消遣而已。(甚至是一种逃避) 21 | 22 | **真实情况是大部分人都说不出来自己真正喜欢什么的**。 23 | 24 | 这是中国教育制度的问题,大家从小学、初中、高中、到大学再到工作 就没有时间或者机会去思考自己真正想干什么。 25 | 26 | 别说在校学生了,就互联网大厂的程序员,我敢说 百分之九十以上 都不喜欢写代码,都感觉写代码是最苦逼的,天天对着屏幕,写写一堆正常人看不懂的英文单词,有啥意思,对吧。 27 | 28 | 但为什么大家都依旧写代码呢。 29 | 30 | **要生活啊,要赚钱啊!** 31 | 32 | 那种可以不考虑经济问题,一言不合就寻找人生意义的选手,都是家里有矿的,那种咱们不讨论。 33 | 34 | 还一些同学迷茫的时候,就放空自己。 还有已经工作的,可能会去一趟西藏,“寻找一下生命的意义”。 35 | 36 | 其实我也是不建议的,**放空自己之后,并不会找到 自己真正的方向,只会更迷茫!** 37 | 38 | 所以,**当你不知道自己真正喜欢什么的时候,就先把眼前的事情做好吧!** 39 | 40 | 如果你知道自己不喜欢计算机,不喜欢写代码,但也不知道自己究竟喜欢什么的时候,那么就先把自己现在该做的事情做好,制定计划,算法题刷题起来,八股文看起来。 41 | 42 | **这才是是最重要的**。 43 | 44 | 希望对录友们有所启发,加油💪 45 | 46 | -------------------------------------------------------------------------------- /problems/知识星球精选/要不要考研.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 | 6 | # 到底要不要读研 7 | 8 | 在[知识星球](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ)里讨论了一下关于要不要读研的问题。 9 | 10 | ![](https://gitee.com/programmercarl/pics/raw/master/pic1/20210613230829.png) 11 | 12 | 其实不少同学纠结于计算机专业要不要考研。 13 | 14 | 我的观点是 **如果认为自己本科毕业 可以拿到大厂的研发岗offer,那么就不用读研**(除非保研到一个特别好的学校了)。 15 | 16 | 那么怎么能发现自己本科毕业能不能拿到大厂offer呢。 17 | 18 | 看看自己学生学哥学姐,大部分人的就业去向,如果很多都可以进入大厂,那么就可以追寻他们的足迹。 19 | 20 | 如果自己学校本科毕业,就业比较一般,那么就去读研吧。 21 | 22 | 当然这里还有一个情况,就是算法岗,算法岗一般要求研究生学历以上。但算法岗现在很卷,985高校研究生,找算法岗的工作都很难,既要顶会,也要coding的能力。 23 | 24 | 目前的现况是很多搞AI的985研究生都在转研发岗,**但如果你依然立志从事人工智能(说明是真的热爱),那么就去读研吧**。 25 | 26 | 研究生毕业去做研发岗和本科毕业做的研发,其工作其实没区别。那么为什么读研呢。 27 | 28 | 现在环境就比较卷,两个候选人,实力差不多,一个本科,一个研究生,价钱也差不多,那么大厂就要个研究生呗,在招生简章里看着也好看,说明公司都是高学历人才。 29 | 30 | 当然一般来说 研究生毕竟又多读了 两三年,普遍会比本科强一些。 31 | 32 | **PS:大厂研发岗校招本科和研究生薪资几乎没啥差别**。 33 | 34 | 35 | 那么话在说回来,**如果打算考研,那么就争取更好学校的研究生,提升一下学历,把考研所付出的努力最大化**。 36 | 37 | 最后关于本科生要不要读研: 38 | 39 | * 本科如果有实力去大厂做研发,那么就去! 40 | 41 | * 如果本科去不了大厂,可以考虑考研,考研是一次提升学历的机会,一旦选择考研这条路,就给自己点压力! 42 | 43 | * 如果知道AI岗位目前就业情况,依然要立志从事AI,那么就去读研 44 | 45 | 46 | -------------------------------------------------------------------------------- /problems/知识星球精选/合适自己的就是最好的.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 | 6 | # 合适自己的,才是最好的! 7 | 8 | 秋招已经进入下半场了,不少同学也拿到了offer,但不是说非要进大厂,每个人情况都不一样,**合适自己的,就是最好的!**。 9 | 10 | [知识星球](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ)里有一位录友,就终于拿到了合适自己的offer,并不是大厂,是南京的一家公司,**但很合适自己,其实就非常值得开心**。 11 | 12 | 13 | ![](https://code-thinking-1253855093.file.myqcloud.com/pics/20210910232502.png) 14 | 15 | 16 | 其实我算是一路见证了这位录友披荆斩棘,**从一开始基础并不好,还是非科班,到 实验室各种不顺利,再到最后面试次次受打击,最后终于拿到自己满意的offer**。 17 | 18 | 这一路下来确实不容易! 19 | 20 | 这位录友是从几年五月份加入星球。 21 | 22 | ![](https://code-thinking-1253855093.file.myqcloud.com/pics/20210910221030.png) 23 | 24 | 然后就开始每天坚持打卡。 可以看看她每天的打卡内容。 25 | 26 | ![](https://code-thinking-1253855093.file.myqcloud.com/pics/20210910222325.png) 27 | 28 | 后面因为天天面试,不能坚持打卡了,也是和大部分同学一样,焦虑并努力着。 29 | 30 | ![](https://code-thinking-1253855093.file.myqcloud.com/pics/20210910222854.png) 31 | 32 | 星球里完整的记录了 这位录友 从五月份以来每天的学习内容和学习状态,能感觉出来 **虽然苦难重重,但依然元气满满!** 33 | 34 | 我在发文的时候 看了一遍她这几个月完整的打卡过程,还是深有感触的。 35 | 36 | [知识星球](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ)里还有很多很多这样的录友在每日奋斗着,**我相信 等大家拿到offer之后,在回头看一下当初星球里曾经每日打卡的点点滴滴,不仅会感动自己 也会感动每一位见证者**。 37 | 38 | -------------------------------------------------------------------------------- /problems/面试题 02.07. 解法更新.md: -------------------------------------------------------------------------------- 1 | # 双指针,不计算链表长度 2 | 设置指向headA和headB的指针pa、pb,分别遍历两个链表,每次循环同时更新pa和pb。 3 | * 当链表A遍历完之后,即pa为空时,将pa指向headB; 4 | * 当链表B遍历完之后,即pa为空时,将pb指向headA; 5 | * 当pa与pb相等时,即指向同一个节点,该节点即为相交起始节点。 6 | * 若链表不相交,则pa、pb同时为空时退出循环,即如果链表不相交,pa与pb在遍历过全部节点后同时指向结尾空节点,此时退出循环,返回空。 7 | # 证明思路 8 | 设链表A不相交部分长度为a,链表B不相交部分长度为b,两个链表相交部分长度为c。
9 | 在pa指向链表A时,即pa为空之前,pa经过链表A不相交部分和相交部分,走过的长度为a+c;
10 | pa指向链表B后,在移动相交节点之前经过链表B不相交部分,走过的长度为b,总合为a+c+b。
11 | 同理,pb走过长度的总合为b+c+a。二者相等,即pa与pb可同时到达相交起始节点。
12 | 该方法可避免计算具体链表长度。 13 | ```cpp 14 | class Solution { 15 | public: 16 | ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) { 17 | //链表为空时,返回空指针 18 | if(headA == nullptr || headB == nullptr) return nullptr; 19 | ListNode* pa = headA; 20 | ListNode* pb = headB; 21 | //pa与pb在遍历过全部节点后,同时指向结尾空节点时退出循环 22 | while(pa != nullptr || pb != nullptr){ 23 | //pa为空时,将pa指向headB 24 | if(pa == nullptr){ 25 | pa = headB; 26 | } 27 | //pa为空时,将pb指向headA 28 | if(pb == nullptr){ 29 | pb = headA; 30 | } 31 | //pa与pb相等时,返回相交起始节点 32 | if(pa == pb){ 33 | return pa; 34 | } 35 | pa = pa->next; 36 | pb = pb->next; 37 | } 38 | return nullptr; 39 | } 40 | }; 41 | ``` 42 | -------------------------------------------------------------------------------- /problems/知识星球精选/面试中发散性问题.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 | 6 | # 面试中遇到发散性问题,应该怎么办? 7 | 8 | 这周在[知识星球](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ)有一位录友问了我这么一个问题,我感觉挺有代表性的,应该不少录友在面试中不论是社招还是校招都会遇到这一类的问题。 9 | 10 | 问题如下: 11 | 12 | ![](https://gitee.com/programmercarl/pics/raw/master/pic1/20210529183636.png) 13 | 14 | 首先面试官评价:基本的知识都懂还可以,但是知识碎片化。 15 | 16 | 因为现在基本大家都是背面经,所以对考点知识点掌握的都不错,确实对整体上理解不够。 17 | 18 | 但如果想对整体上理解深入,需要花费很大精力的,而且要把书看的很透彻,那这种候选人基本都是拔尖的。 19 | 20 | 关于操作系统啊,数据库等等,大多数录友应该都是靠面经,其实背面经也是最高效,性价比最高的方式的,如果真的去把书看透,一本《深入理解计算机系统》够看一年了。。。。 21 | 22 | 所以面试官基本不会因为这个问题而把你pass掉,那位提问的录友也是顺利进入了三面。 23 | 24 | 那么面试中遇到这种发散性问题应该怎么办呢? 25 | 26 | 其实他问的这种问题,**就没指望你能说出 正确的答案,这是没有标准答案的**,例如淘宝京东的那种登录的场景 没有经历过 是不知道究竟怎么回事的。 27 | 28 | 而问你对操作系统的理解,也是千人千面没有标准的。 29 | 30 | 遇到这种问题,你就结合自己的想法,大胆说,不要说这个我不知道,那个我没遇到过之类的。 31 | 32 | 你说的解决方案,一定是有问题的,面试官在质疑你的时候,**你要表现出很兴奋,积极和面试官讨论:为什么不对**,然后说出你的观点,结合你所知道的理论知识。 33 | 34 | 大胆说,不要怕,一般情况你的理论知识都比面试官强,面试官工作好多年了基础知识早忘了,基本都是面试你前一天突击一个小时(暴漏真相了哈哈哈) 35 | 36 | **忌讳:面试官一质疑你,你就开始怀疑自己,心想那我说的不对吧,然后就不说话了。。。** 37 | 38 | 最后这种发散性的问题,也没法去专门准备,因为这种问题主要是**考察候选人对技术的态度和沟通能力!** 39 | 40 | 所以大家如果在面试遇到这一类发散性问题,一定要积极沟通,**表现出你对技术的追求和优秀的沟通能力**。 41 | 42 | **注意 和面试官讨论的时候要面带微笑,不要板着脸,面试官也会喜欢以后和这样的人做同事!** 43 | 44 | 好咯,心法已经传授给大家了。 45 | 46 | -------------------------------------------------------------------------------- /problems/知识星球精选/如何权衡实习与秋招复习.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 | 6 | # 已经在实习的录友如何准备秋招? 7 | 8 | 最近在[知识星球](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ)一位录友问了实习生如何权衡工作和准备秋招的问题。 9 | 10 | 11 | ![](https://code-thinking-1253855093.cos.ap-guangzhou.myqcloud.com/pics/20210703230618.png) 12 | 13 | 其实这个问题挺有代表性,我之前一直讲的都是没有去实习的录友应该怎么怎么办,其实已经在大厂实习的录友也有很多烦恼。 14 | 15 | 这里我说一说已经有大厂实习经历,准备秋招的重点。 16 | 17 | 一般来说有大厂的实习经历,**面试官的兴趣都在大厂实习的项目经验上**。 18 | 19 | 所以关于权衡实习和准备基础这两个方面,**可以把主要精力放在项目包装上,其次是看基础**。 20 | 21 | 要在包装实习项目上多花点心思,实习生做的项目偏上业务很正常,不可能让实习生搞太复杂的,一旦出了问题还得导师背锅。 22 | 23 | 自己干的活,或者项目很简单 不要紧,可以好好包装一下,如果没有难点,**可以结合业务自己“造”难点**,大厂内部研发文档都特别多而且特别全。 24 | 25 | 例如整个项目的立项,各个模块的开发,以及研发中遇到的困难,技术选型,上线事故,等等这些都是有完整的文档记录的。(当然大厂也有一些部门研发流程很原始,没有文档,全靠口述) 26 | 27 | 从这些文档中也可以找出 难点糅合到自己的项目中。 28 | 29 | 假如线上出了事故,虽然自己不用去排查但可以跟着同事们一起看问题,一起分析,甚至帮他捞捞日志,打打下手。 30 | 31 | 这次事故的表现,起因,定位等等,排查问题的同事都会记录的清清楚楚,放在项目文档下。 32 | 33 | 可以把这些文档都多看看,然后就可以转变成自己排查线上事故的经历了。 34 | 35 | **这种经历在面试官来看就是很大的加分项了**。 36 | 37 | 所以在大厂实习,想包装自己的项目方法有很多,只不过一些同学初入职场,对自己有帮助的资料或者内容不太敏感,不善于利用已有的资源。 38 | 39 | **需要过来人点一下,基本就上道了,哈哈哈**。 40 | 41 | 当然不是说只要在大厂实习,基础完全就不用看了,抽空也要看,只不过 项目经验(项目的包装)更重要! 42 | 43 | 关于提前批,一般来说本厂实习生是不能参加提前批的。 44 | 45 | 你可以参加 其他大厂的提前批,只不过参加提前批是有代价的,面试不通过都是有记录的,得看自己项目准备的如何,能不能拿出手,而且一边实习一边面试可能也不太方便,如果想试一试,就找自己不想去的企业的提前批试试水! 46 | 47 | 48 | -------------------------------------------------------------------------------- /problems/知识星球精选/HR特意刁难非科班.md: -------------------------------------------------------------------------------- 1 | 2 |

3 | 4 | 5 | 6 | 7 | # HR特意刁难非科班! 8 | 9 | 不少录友都是非科班转程序员,或者进军互联网的,但有一些HR在HR面的时候特意刁难大家。 10 | 11 | 正如[知识星球](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ)里,这位录友所遭受的情景。 12 | 13 | ![](https://code-thinking-1253855093.file.myqcloud.com/pics/20211006230202.png) 14 | 15 | 1. 你的研究方向并不是这个方面的,你为什么要转行? 16 | 2. 你和非科班的同学相比肯定有一些劣势,你打算怎么赶上他们?或者是你如何应对你作为非科班生在工作中的挑战? 17 | 18 | 以下是我的回答: 19 | 20 | 对于问题一,你这么说没问题,可以再润色一下,说一说自己看过哪些技术大牛的传记,例如《黑客与画家》,对自己影响很大,然后对编程就非常感兴趣,想从事这个行业 等等。 或者说 你感觉 新能源汽车是以后非常明确的方向,而自动驾驶是新能源汽车的标配,所以想投身这个行业。 21 | 22 | 问题二: 首先要自信起来,说:在技术方面和对编程的热情方面,我不比科班同学差,因为大学里教的内容和企业要求的基本脱钩的,大家准备面试进大厂都是靠自学,**反而因为我是非科班,我更加的努力,也特别珍惜来之不易的机会**。 23 | 24 | 如果要说科班同学有什么优势的话,我感觉他们的学习编程的氛围会好好一些,也就是遇到问题大家能一起交流,因为我车辆工程专业,所以我会经常去蹭计算机的课,也会去认识很多计算机专业的同学和他们一起讨论问题。 25 | 26 | 总之在HR面的时候,不要说自己哪里的缺点,也不说自己哪里技术掌握的不好,**HR不懂技术,你说自己哪里不懂,他就真认为你不懂了**。 27 | 28 | 缺点就说一些不痛不痒的,甚至化缺点为自己的优势。 29 | 30 | 例如问你的缺点是什么? 31 | 32 | **可以说自己有时候 对技术细节过于执着,以至于影响整体的进度**。 33 | 34 | 这种缺点 无形之中 就体现出自己 对技术的热爱和专研 (起到装逼于无形的效果),而且 这种缺点 是分分钟就可以改的。 35 | 36 | 如果问你 :作为非科班生在工作中的挑战? 37 | 38 | 你也这么说:其实大家都是靠自学,如果说非科班在工作中遇到的挑战,我相信 科班同学在工作中也是遇到一样的挑战,工作之后自学能力更加重要,互联网变化是飞快的,只有自学能力强的同学才能跟上步伐。 39 | 40 | 然后随便举例一下,说明自己自学能力如何如何的强,就可以了。 41 | 42 | **总之不能示弱,不能说自己哪里不好,哪里不行!** 43 | 44 | HR也不懂技术,主要就是看你的态度。 45 | 46 | 就酱,希望对录友们有所启发,加油💪 47 | 48 | -------------------------------------------------------------------------------- /problems/知识星球精选/初入大三选择考研VS工作.md: -------------------------------------------------------------------------------- 1 | 2 |

3 | 4 | 5 | 6 | 7 | # 初入大三,考研VS工作 8 | 9 | 9月份开学季,已过,一些录友也升入大三了,升入大三摆在自己面前最大的问题就是,考研还是找工作? 10 | 11 | 在[知识星球](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ)里就有录友问我这样一个问题, 其实每个人情况不一样,做出的选择也不一样,这里给大家分享一下,相信对你也会有启发。 12 | 13 | ![](https://code-thinking-1253855093.file.myqcloud.com/pics/20211002110618.png) 14 | 15 | 以下是我的回答: 16 | 17 | 首先我是考过研的,比较幸运一次就上岸了,这里说一下我的心得。 18 | 19 | 你才刚刚大三 就已经做了这么充分的准备了,那我倾向于 选择直接工作。 20 | 21 | 因为现在你准备的这些,都是找工作需要的,也都是实用的技术。 22 | 23 | 如果你明年初就开始准备考研了,那么你现在学的这些东西,就是半途而废了,考研一年 能让你的 编程技能水平 回到解放前(考过研的同学应该都懂的)。 24 | 25 | 不能说考研的内容一点用都没有,如果从技术学习的角度来说,其投入产出性价比极其极其极其的低。 26 | 27 | 举一个不太恰当的例子,考研就是大家一起学 “一个不太实用的知识”,看谁学的好。 28 | 29 | 所以考研其实更多的是学历上的提升,如果想通过考研,或者读研学习到什么? **还是不要有这个打算,大概率会让你失望的**。 30 | 31 | 正如你所说的,你有信心成为年级里比较优秀的(就业方面),也正是 准备的早,所以给了自己信心。 32 | 33 | 而且你们学校还有很多学长本科毕业就找到了好的工作,完全可以追随他们的足迹。 34 | 35 | 去考研的话,有信心考上更好的学校,当然可以,关键是 考研也是千军万马过独木桥,特别是计算机考研,特别是985名校,非常的卷。 36 | 37 | 如果没考上研究生,再去找工作就很被动了。 38 | 39 | 这也是为什么,很多一战失利都会选择二战,因为如果失败,损失很大,所以这条路还要继续走下去,一定要上岸。 40 | 41 | 再结合自己的情况,假如能考上,但考上了一所一般学校,其实对自己来说都是损失。 毕业之后 未必 有现在直接找工作找的好,年轻就是优势,特别是做研发,读研出来也是做研发,本科也是做研发,其实没太大区别的。 42 | 43 | 所以 如果本科毕业的学长学姐 就业也不错,可以追随他们的脚步,毕竟你已经开始准备了。 44 | 45 | **如果有信心要冲 名校计算机研究生,或者说对某一所大学有情节,添补高考遗憾,那么可以冲,考上了是值得的**。 46 | 47 | 48 | 当然也可以多和身边的 师兄 师姐交流,看看他们的说法,综合评估一下。 49 | 50 | -------------------------------------------------------------------------------- /problems/知识星球精选/提前批已经开始了.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 | 6 | # 不知不觉华为提前提已经开始了 7 | 8 | 最近华为提前批已经开始了,不少同学已经陆续参加了提前批的面试。 9 | 10 | 在[知识星球](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ)上就有录友问我这么个问题: 11 | 12 | ![](https://code-thinking-1253855093.cos.ap-guangzhou.myqcloud.com/pics/20210711002802.png) 13 | 14 | 华为是比较看重学历的,如果学校比较好(985以上),华为的面试会随意一些,几乎就是走一个流程。 15 | 16 | 我记得当初校招的时候,华为来我们学校就是 几个大巴把整个计算机学院的同学拉到酒店,批量面试,面试过程差不多就是走个形式,大家基本都拿到offer了。 17 | 18 | 不是说 非985/211的同学 技术就不好,而是当企业每年要招上万人的时候,通过学历还筛选相对来说是 效率较高且成本最低的一种方式。 19 | 20 | 不过现在竞争越来越激烈了,华为也很少这种粗暴方式来召人。再说华为给出的薪酬相对互联网大厂也 很有竞争力,发展前景也很不错。 21 | 22 | 那么在说一说面试的内容。 23 | 24 | 可能有的同学感觉,我为了面试,准备了这么多,结果面试都没问,就问问项目问问编程语言就完事了。 25 | 26 | 这其实很正常! 27 | 28 | 不同的公司,同一个公司不同部门,同一个部门不同面试官 面试风格都不太一样。 29 | 30 | 可能部门就比较缺人,面试官看一下 简历 学校可以,技术看上去还凑合,项目也还行,那么面试可能就放水一点,然后就过了。 31 | 32 | 毕竟面试官也很忙,在大厂谁都不想当面试官,都是工作之余加班的工作量,**所以面试官也想快点结束**。 33 | 34 | 还有另一种可能,就是部门已经招满了,但依然安排了面试,那么面试官就随便问问,然后也不会招人了。 35 | 36 | 还有一种,就是有的面试官就习惯考察算法题,问完算法了,其他的他也就不会问了。 37 | 38 | 因为操作系统,网络,数据库这些面试官在面试之前也要突击准备的,工作那么多年,都忘的差不多了,**所以要复习一波,这也是工作(都是加班啊!)**。 39 | 40 | 甚至可能面试官前天刚要和女朋友过生日,然后就没准备计算机基础方面的内容,索性面试的时候也就不问了..... 41 | 42 | 这都是有可能的,很多同学可能没做过面试官,所以对一些面试过程就容易想不通,其实面试官也是普普通通的打工仔,他也不想加班,也想只要人品端正,积极肯干,随便召个技术差不多的就算了,哈哈哈。 43 | 44 | 所以说,面试有的时候也很看缘分的,大家辛辛苦苦造火箭,结果面试都没问是很正常的。 45 | 46 | 大家也放平心态,把该做的做好,剩下的交个天意了。 47 | 48 | 49 | -------------------------------------------------------------------------------- /problems/知识星球精选/非科班的困扰.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 | 6 | # 非科班的困扰! 7 | 8 | 在[知识星球](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ) 里很多录友都是非科班转码的,也是要准备求职,或者准备明年秋招,非科班的录友其实对 准备找工作所需要的知识不太清楚,对其难度也不太清楚,所有总感觉准备起来心里没有底。 9 | 10 | 例如星球里有这位录友的提问: 11 | 12 | ![](https://code-thinking-1253855093.file.myqcloud.com/pics/20211024102300.png) 13 | 14 | 我在知识星球里,给出了详细的C++后端学习路线,包括计算机基础的学习路线, 15 | 16 | ![](https://code-thinking-1253855093.file.myqcloud.com/pics/20211024103006.png) 17 | ![](https://code-thinking-1253855093.file.myqcloud.com/pics/20211024103108.png) 18 | 19 | 当然路线很长,这里我就截图了一部分。 20 | 21 | 但即使这样,其实非科班的录友也不容易量化具体的工作量究竟多大。 22 | 23 | 以下是我对这位录友的回答: 24 | 25 | ---------------- 26 | 27 | 具体学习时间 一般是不好量化的。 28 | 29 | 一本书,有的同学 一周就看完了,有的同学 两个月看不明白,**基础程度,学习速度,每天的投入时间,以及效率**都是不一样的。 30 | 31 | **所以要靠自己 规划时间,自己是最了解自己的**。 32 | 33 | C++primer 不要耗太久,差不多就去看 effective C++。 34 | 35 | 还有计算机求职需要准备的知识不是线性排列的。 36 | 37 | 例如很多非科班的录友可能会这样安排: 几个月搞定编程语言,几个月搞定算法,几个月搞定操作系统! 38 | 39 | **如果这么学的话,那就凉凉了**。 40 | 41 | 求职准备主要围绕这么几块:编程语言 + 算法 + 计算机基础(操作系统,数据库,网络,设计模式)+ 项目 。 42 | 43 | **这几块都可以一起搞的,一天都要分配点时间,知识错开点来学,效率更高**。 44 | 45 | 每一块知识,每天都要投入一点,例如,例如一天算法几个小时,编程语言几个小时,计算机基础几个小时,项目几个小时,这样分配,当你发现 操作系统比你想象中的难,你就 下周及时调整计划,操作系统每天多分配时间。 46 | 47 | **正常的学习节奏是这样根据自己的掌握程度动态调整的**。 48 | 49 | 在整体进度上,可以先保证都过一遍,第一遍看的时候,不要死扣细节,会非常耽误时间,先过一遍有整体性的把控 更重要。 50 | 51 | 之后在针对面经或者八股文,去一个难点一个难点的攻克。 52 | 53 | 希望对非科班的录友们有所启发,加油💪 54 | 55 | -------------------------------------------------------------------------------- /problems/知识星球精选/逼签.md: -------------------------------------------------------------------------------- 1 | 2 | # 遭遇逼签,怎么办? 3 | 4 | 最近各大公司陆续开奖了,也有不少公司开始逼签了。 5 | 6 | 为什么会有逼签呢,无疑就是 这家公司你不太想去,但还想要一个保底(备胎),同时这家公司也知道自己竞争力可能不是很大,也不想当大家的备胎,所以就要三天内必须签三方。 7 | 8 | 如果是心仪的公司要求三天内签三方,我相信大家就没有被逼签的感觉了,哈哈哈 9 | 10 | [知识星球](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ)里很多录友都问我,XX公司又要逼签了,怎么办。 我在公众号也分享一下,希望对大家有所帮助。 11 | 12 | ![](https://code-thinking-1253855093.file.myqcloud.com/pics/20211017093816.png) 13 | 14 | 以下是我的回答: 15 | 16 | TPLINK 的嵌入式,确实有点偏,但钱给的还真多 (估计是发现不好找人了)。 17 | 18 | 从发展来看,当然百度 虾皮 是首选,百度一般薪资不高,但我估计 虾皮薪资应该可以。 19 | 20 | 虾皮如果 10月底 才下offer的那,一般有更好的offer的同学 指定早就签了,我估计虾皮是能接受 毁约三方 也就是等你毁约三方,再签虾皮的 (注意,这是我猜的),要不 10月底 在下offer,优秀的毕业生遭抢没了。 所以如果能联系上HR的话,可以问一问,是否一定要三方。 21 | 22 | 你去签 TPLINK 三方的时候 也问问,毁约的流程,TPLINK 什么时候会退给你三方,如果是 TPLINK HR很坚决 不接受毁约的话,就等百度 和虾皮吧,到时候谈薪资的时候 拿tplink这个作为依据,高点要薪资。 23 | 24 | 如果 TPLINK HR 能接受毁约,给出 毁约 流程的话,那就签了。 (但这里不能排除 HR 口是心非,说是能毁约,最后不给你退三方的情况,所以多问问 有没有师兄毁约 TPLINK成功的) 25 | 26 | 我当初校招的时候签的就是华为,也给三方了,毁约去的腾讯。我腾讯都入职了,华为才把三方退回来,我在补上三方,所以腾讯是不要求三方的,只要人去了就行。这个也看公司的。 27 | 28 | ------------- 29 | 30 | ![](https://code-thinking-1253855093.file.myqcloud.com/pics/20211017094407.png) 31 | 32 | 以下是我的回答: 33 | 34 | 7月开始自学c++,秋招就能拿到这些offer已经很棒了👍 35 | 36 | 先看逼签的这两家,其实我都不太了解,我的朋友们主要都在互联网圈,所以 没有认识的朋友在这两家公司。 37 | 38 | 不过 thoughtworks 网评不太好,说是外包公司, 中孚信息 至少是土生土长的企业,做网络安全,也是上市公司,至少会靠谱一些。 39 | 40 | 华为成都 光产品线的测开,如果你想真的有增进技术的心,测开就稍差了一些。 41 | 42 | 相对来说 小米南京的offer 还不错,但还在池子里。 43 | 44 | 如果逼签的话,优先考虑中孚吧。 45 | 46 | 关于 好好沉淀准备春招 当然是可以的,但不是每个同学都是劲再去冲春招了,找工作都是一鼓作气,如果你还能高强度的准备面试冲刺春招,当然是好的。 47 | 48 | 关键是 还有外部因素,毕业的事,以及大家该保研的保研了,找到工作了都吃喝玩乐了,天天聚餐,这个氛围下,你还能不能继续高强度冲刺了, 这才是你要考虑的。 49 | 50 | 加油💪 51 | 52 | -------------------------------------------------------------------------------- /problems/知识星球精选/英语到底重不重要.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 | 6 | # 对程序员来说,英语到底重不重要 7 | 8 | 在[知识星球](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ)有一位录友问了我这么一个问题。 9 | 10 | ![](https://gitee.com/programmercarl/pics/raw/master/pic1/20210605193955.png) 11 | 12 | 这个问题我曾经在上学的时候也思考过。 13 | 14 | 这次正好来好好说一说。 15 | 16 | 当时我搞ACM的时候都是英文题目的,哪会有中文题目,现在力扣全面汉化也是最近几年的事情。 17 | 18 | 如今又工作了这么多年后重新看待这个问题,又有更全面的看法了。 19 | 20 | 其实我想说,**对英语对程序员即重要,也不重要!** 这是要看环境,看背景的。 21 | 22 | 如果你现在在准备秋招,或者是跳槽,目标是冲刺国内大厂,那么暂时不用花费精力学英语,就算四级都没过,大厂面试官也不会问你过没过四六级的。 23 | 24 | 貌似华为对英语四六级是有要求的,如果面试BAT,英语不是关键性问题。 25 | 26 | 但工作之后,英语其实就很重要了,也要注意程序员英语和普通英语是不一样的。 27 | 28 | 一手的技术资料,和优秀的问答 基本都是英文的,国内的资料都是别人嚼过的,质量参差不齐。 29 | 30 | 而且国内的问答社区其实环境并不好(懂的人都懂),真正解决问题,还得靠Stack Overflow。 31 | 32 | **所以技术文档(英文),Stack Overflow , Quora才是程序员的利器**。 33 | 34 | 工作以后如果你把程序员英语(注意不是普通英语)练好,其实对技能和视野的提升是很有帮助的。 35 | 36 | 这里为什么强调是程序员英语呢, 因为有太多专业词是CS特有的,而不是日常英语。 37 | 38 | **继承,多态,变量,英文怎么说? 估计可以难住不少人了**。 39 | 40 | 所以当我们查问题的时候,第一反应 一定是用 中文关键词去搜索,因为我们不知道对应的英文关键词(也懒的去查一下)。 41 | 42 | 所以英语好,这是一种技术壁垒,可以任意遨游在中文和英文的世界里,有两极的思考! 43 | 44 | **那么对程序员来说,英语口语重要么?** 45 | 46 | 如果你直接想去外企的话,练一练吧,也是挺重要的,如果在国内的话,用处不太大。 47 | 48 | 那一定有人说了:练好口语 一定是有利的。 49 | 50 | 这个我也 赞同,练啥其实都有有利的,但我们要看**投入产出比** 51 | 52 | 我在学校的时候英语口语还是挺不错的,当时学校的留学生我基本都认识,和他们扯扯皮没问题,可工作这些年之后,全!都!还!回!去!了! 53 | 54 | 所以如果练习口语,一定要有目标,要么就是雅思托付考试要出国,要么就一定要去外企找机会transfer美帝,这样有一个环境可以一直保持下去。 55 | 56 | 否则,花费大量时间练习,其实仅仅是感动自己,过不了多久,就都还回去。(例如说我,哈哈哈哈) 57 | 58 | 59 | -------------------------------------------------------------------------------- /problems/知识星球精选/秋招的上半场.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 | 6 | # 秋招上半场的总结 7 | 8 | 八月份已经接近尾声,不少录友已经在[知识星球](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ) 已经总结了秋招的上半场。 9 | 10 | ![](https://code-thinking-1253855093.file.myqcloud.com/pics/20210829214839.png) 11 | 12 | 可以看出 这位录友也是身经百战,目前也拿到了几个offer。 13 | 14 | 星球里还有不少录友已经拿到了字节,阿里,百度提前批的offer。 15 | 16 | ![](https://code-thinking-1253855093.file.myqcloud.com/pics/20210829231035.png) 17 | 18 | 不过绝大部分录友还在经受着考验,处于焦虑的状态,秋招上半场也是几多欢喜几多愁。 19 | 20 | 找工作其实是一个很虐心的过程,没有offer、没准备好、面试没发挥好、差一点就能把这题过了 等等,每一个场景都给大家增添一份焦虑。 21 | 22 | 星球里有一些录友就找到了一个方向,或者一个准备同一家公司的伙伴,就会好一些。 23 | 24 | ![找到了同伴交流](https://code-thinking-1253855093.file.myqcloud.com/pics/20210820093109.png) 25 | 26 | **有时候,有压力,自己憋着,没人交流,只会压力越来越大**。 27 | 28 | 对于还没有offer的录友,我对大家的建议也是,**心态要稳住,要适当放低预期,不是所有人都要大厂,但不能放低自己对学习的要求!** 29 | 30 | 有些同学,经过几次面试的打击之后,直接就自暴自弃,狂玩几天想释放压力,这么做的结果,只会压力越来越大。 31 | 32 | 所以,**秋招进行时,大家不要过于放松,无论什么情况,只要没有拿到心仪offer,就不能放松,一旦放松之后,换来的就是更看不到希望**。 33 | 34 | 有的同学可能学校不好,有的同学是转行计算机,一路下来确实艰难。 35 | 36 | 我在星球里,看到的不仅是大家准备秋招过程的每日学习总结、打卡,也看到了一些录友的不容易。 37 | 38 | ![](https://code-thinking-1253855093.file.myqcloud.com/pics/20210829221259.png) 39 | 40 | 说实话,看着评论区,还是很感动的,估计这位 打卡的录友,也得到了很大的鼓励。 41 | 42 | 这可能是 成千上万 目前正在冲刺秋招应届生 的一个缩影。 43 | 44 | 面试不仅仅是只看技术,也挺看缘分的,有的同学可能感觉莫名其妙的就挂了,有的同学可能感觉莫名其妙的就拿到了offer。 45 | 46 | 我就简单列举几个原因。 47 | 48 | * 可能部门缺人,或满了 49 | * 可能是当天面试的同学都不太行,就矬子里拔大个 50 | * 可能之前有几个优秀的毕业生,但按照之前的标准都没过,然后面试官发现这么下去招不到人了,一下子就把标准降低了,然后轮到了你,你感觉你发挥的并不好,但也给你offer了。 51 | 52 | 所以面试也有很多很多其他因素,也很看缘分。 53 | 54 | 大家放平心态就好。 55 | 56 | -------------------------------------------------------------------------------- /problems/知识星球精选/入职后担心代码能力跟不上.md: -------------------------------------------------------------------------------- 1 | 2 |

3 | 4 | 5 | 6 | 7 | # 入职后担心代码能力跟不上 8 | 9 | 在[知识星球](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ)上,很多录友已经担心自己去了公司工作以后,代码能力跟不上,会压力很大。 10 | 11 | ![](https://code-thinking-1253855093.file.myqcloud.com/pics/20211031202952.png) 12 | 13 | 其实 星球里 也有很多 已经确定offer的录友,想在入职之前提升代码能力,或者说 如何可以更快的融入项目组。 14 | 15 | ![](https://code-thinking-1253855093.file.myqcloud.com/pics/20211031203944.png) 16 | 17 | 这里我把应届生刚刚工作需要培养的能力都说一说,其实也适用于毕业一两年的录友。 18 | 19 | ## 代码能力 20 | 21 | 练习代码能力最直接的方式就是多写,最简单的是用你的语言写一个管理系统,甚至你每天刷刷题,也是可以的。 22 | 23 | 再直白一遍,不是有26种设计模式,你全都实现一遍,即锻炼 代码能力,还学习了设计模式,等入职之后多看项目代码,看看大家在设计上使用了那种设计模式,或者说哪里还可以优化。 24 | 25 | 设计模式可以说 面试中最实用的知识的,大部分面试内容,工作中其实都用不上,所以大家会发现面试造大炮,工作拧螺丝。 26 | 27 | ## 心态 28 | 29 | 工作之后 从心态上来说,要不怕困难,不怕bug,不怕未知技术。 30 | 31 | 很多同学之所以代码能力弱,**就是太怕 难点**,遇到点 困难 就想:恨不得谁告诉我应该怎么怎么办得了,而不是自己去解决问题。 32 | 33 | 要善于使用搜索引擎,如何所谓问题是一个技术活,有的问题你怎么搜都搜不出来答案,但有的同学一搜 就搜出来了。 34 | 35 | 为什么呢? 36 | 37 | 这是遇到问题,提取关键词的能力,很多同学遇到问题,不知道用什么关键词去搜。 38 | 39 | **还有要有一种 越挫越勇 的精神**,这样你后面 的困难就会越来越少,也会培养出一种自信。 40 | 41 | 写代码也需要自信,工作之后 经常 有一些比较难任务,有的 同学就不敢接,怕做不出来,有的同学就敢接,并不说这位同学技术上一定强,而是他有自信。 42 | 43 | **这种自信都在是以往 解决各种问题,排查各种bug,练就出来的**。一旦拥有自信,那能量就是 摧枯拉朽,真正的逢山开路遇水搭桥。领导也喜欢这样的组员 44 | 45 | ## 快速成长 46 | 47 | 刚入职的时候,不要怕问问题,不要怕出错,不要怕不好意思。 48 | 49 | 因为你是新人,就算问简单的问题,大家不会嫌弃你,但 这个新人窗口期是很短的,如果 过了几个月 还问一些非常基础的问题,那么 可能职场上就不太好了。 50 | 51 | 所以要在新人窗口期,快速成长,我看过太多的应届生,入职的时候 都是畏头畏尾,然后 过了新人期,能力还没有提高,还问很基础的问题,这样 项目组也不会分给他 有难度的任务,他也就得不到锻炼,越得不到锻炼,就能力越没提升,就越没自信,就越接不到有难度的活,然后陷入死循环! 52 | 53 | 54 | 综上,算是从学校到职场的上的一个转变。 希望对大家有帮助。 55 | 56 | -------------------------------------------------------------------------------- /problems/知识星球精选/博士转行计算机.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 | 6 | # 本硕非计算机博士,如果找计算机相关工作 7 | 8 | 在[知识星球](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ)里,有一位博士录友,本硕都不是计算机,博士转的计算机,问了这样一个问题 9 | 10 | ![](https://code-thinking-1253855093.file.myqcloud.com/pics/20210903213924.png) 11 | 12 | 一下是我的回答,在这里分享给大家。 13 | 14 | 我的一些研究生同学,都在读博,有的毕业有的还没毕业,平时和他们聊,对博士就业也是有一定的了解,这里说一说我的建议。 15 | 16 | 对于博士,强烈建议能去高校就去高校,这样最大程度发挥出了博士的好处,赚国家科研经费的钱还是香的。 17 | 18 | 虽然现在对青年研究者并不友好,基本经济大头都被实验室boss拿走了。 19 | 20 | 但高校壁垒高,外界再优秀的人才,也进不去和你竞争,所以可以小范围的卷。出来的话,就是和整个社会AI领域甚至和研发的同学一起卷。 21 | 22 | **在企业 是谁有能力谁就上, 在高校,至少你得有博士学位才能上! 这就是很高的门槛了**。 23 | 24 | 25 | 而且能给博士提供岗位的企业少之又少,所以博士的就业面反而窄了。 26 | 27 | 可能有同学想,薪酬要的低一点还不行么,其实博士毕业对薪资还是有要求的,如果薪资和本科,硕士应届生一样的话,自己也接受不了。 28 | 29 | 所以高校能给博士的机会更多一些,不过现在高校也是 青年科研人员都是 五年合同制,如果没有产出,也要走人了,压力也很大。 30 | 31 | 及时这样,还是建议能去高校去高校,当然这需要有心善、能力强、有人脉的博导,那是最好的了,(**注意这里选择博导,心善是最重要的一个选项**) 32 | 33 | 实在去不了高校,接下来我们在看企业。 34 | 35 | 博士找工作不建议走正式招聘流程,例如走官网投递之类的,面试都没戏。 36 | 37 | **AI岗现在对coding能力,工程能力要求都很高,企业现在特别喜欢有科研能力和工程能力的博士**,但这种人才还是稀缺的,大多数博士可能不会做那么多的工程项目,更别说还是本硕是非计算机专业的博士。 38 | 39 | 所以博士找工作要靠门派,最好你的导师,实验室大boss 有哪些徒弟在外面企业,BAT华为之类的干的很好,能联系上,就是同一门派的师兄弟。 40 | 41 | 联系上,做一个内推,他们看一下你的博士论文和研究成果,如果行的话,面试基本就是走个流程,这样就很舒服了。 42 | 43 | 如果上来一波算法题,然后 操作系统,网络 数据库,这样考察下来,基本计算机专业的博士也招架不住,毕竟大多数博士是科研型的,一般来说工程能力比较弱,计算机基础哪些基本也没时间看。 44 | 45 | 46 | 再说一说非科班博士如果有机会去面试,**一定要重点突出知识的迁移能力,和对学术的研究能力,这个是硕士本科生所不能具备的**。 47 | 48 | 企业还是比较喜欢有快速学习能力和知识迁移能力的人,因为技术是不断在变化了,只有学习能力足够强再能跟上。 49 | 50 | 所以**不能和本科硕士去硬拼专业技能的储备量**,特别是最新最热的技术(因为本来就是非科班嘛), 要体现出博士对技术对知识的理解,这是你的优势。 51 | 52 | 以上是我的回答,希望多大家有所启发。录友们周末愉快🌹 53 | 54 | -------------------------------------------------------------------------------- /problems/知识星球精选/秋招进行中的迷茫与焦虑.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 | 6 | # 秋招进行时,其实大家都很焦虑 7 | 8 | 大家应该都发现了,提前批和秋招都越来越提前的,大部分的录友此时的心态还是挺焦虑的。 9 | 10 | 特别是大三的同学吧,同时面临这找工作和考研两个方向的诱惑。 11 | 12 | 一位录友就在[知识星球](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ)问了我这个问题: 13 | 14 | ![](https://code-thinking-1253855093.cos.ap-guangzhou.myqcloud.com/pics/20210724183240.png) 15 | 16 | 其实 互联网35岁中年危机,应该吓退了不少小鲜肉,互联网35岁中年危机是真的,网上哪些关于裁员的消息 大多数也都是真的。 17 | 18 | 但我想说:特别是正在找工作的同学,大家应该都是 95后,00后,可以先不用想那么长远,能把未来五年规划好,就不错不错的了,现在行业的变化,都是两三年一变天,等大家35岁的时候,都不一定啥样了。 19 | 20 | 而且卡哥还替大家先趟趟路,哈哈哈 21 | 22 | 现在的大三,最忙的就是两伙人,**考研的和找工作的,这两条路都挺难的**。 23 | 24 | 另外还有不少录友应该在考研与找工作之间摇摆。可能有的学校大多数都在找工作,有的学校大多数都在考研,不过应该考研占绝大多数。 25 | 26 | 关于考研我的观点是,如果 本科毕业能拿到大厂或者中厂offer,可以不考研,看看自己比较优秀的学长学姐,毕业都去哪了,是否去了大厂,如果比较优秀的学长学姐 就业也一般,我还是推荐读研的,因为顺便也提升一下学历。 27 | 28 | 但有的同学是从大一入学就规划了自己 以后直接工作的,这种无论学校如何,我都是比较支持的! 29 | 30 | **因为从大一就明确自己的方向,按找工作的要求来学习,一般来说 最后找工作都不会差**。 31 | 32 | 最危险的是,大一大二没计划,到了大三开始摇摆,考研还是找工作。这种是最危险的,如果在纠结一阵纠结到 现在的话,那基本哪条路都走不好了。 33 | 34 | 对于现在找工作的录友,可能发现身边的同学都在考研,而且在准备找工作中,可能还没有明确的学习计划,东打一发西扯一下,就会很焦虑,主要也是身边一起工作的同学可能不多,交流的少。 35 | 36 | 找工作是一个累心的过程,非常累,恨不得哪家公司赶紧给我个offer,让我干啥都行,甚至怀疑自己是不是要再去考研。 37 | 38 | **其实这时候,不是自己方法不对,也不是自己选择的路错了,而是需要一个过来人,给你打打气**。 39 | 40 | 静下心来,把最近开始面试的公司排一下,把自己还要学习的内容做好计划,都列出来,按着一步一步去执行,心里会踏实的多。 41 | 42 | 再说考研,考研也一点都不轻松,进大厂卷,**现在计算机考研比进大厂还卷(特别是名校计算机)**,如果考研没考上,找工作还挺难的,毕竟考研那套知识,对于找工作来说几乎没啥用。 43 | 44 | 所以不论是找工作,还是考研,大家都是一样的焦虑,每条路都不好走,但自己一旦选择了,就坚持下来,走好自己的路。 45 | 46 | 话再说回来,**现在不论身在什么阶段,都离不开“卷”,就算最后进了大厂工作,依然也是卷**。 47 | 48 | 大家都感觉自己准备面试好辛苦,好心累。其实给你面试的面试官,可能自己手上的模块线上又出问题了,还要担心年底是不是要背锅了,是不是年终没了,晋升不了了,是不是要准备跳槽了,甚至应届生的工资比自己的还高 等等。 49 | 50 | **所以面试官也许比你还心累!** 51 | 52 | 是不是想到这里,心里就舒服点了,哈哈哈哈,其实是有时候自己很迷茫但没有人沟通,就会陷入一个死循环,只要和过来人聊一聊,没啥大不了的。 53 | 54 | 大家其实这这样。 55 | 56 | -------------------------------------------------------------------------------- /problems/前序/成都互联网公司总结.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 | 6 |

7 |

欢迎大家参与本项目,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!

8 | 9 | 10 | 11 | 12 | # 成都互联网公司总结 13 | 14 | **排名不分先后,个人总结难免有所疏漏,欢迎补充!** 15 | 16 | ## 一线互联网 17 | * 腾讯(成都) 游戏,王者荣耀就在成都! 18 | * 阿里(成都) 19 | * 蚂蚁金服(成都) 20 | * 字节跳动(成都) 21 | 22 | ## 硬件巨头 (有软件/互联网业务) 23 | 24 | * 华为(成都) 25 | * OPPO(成都) 26 | 27 | ## 二线互联网 28 | 29 | * 京东(成都) 30 | * 美团(成都) 31 | * 滴滴(成都) 32 | 33 | ## 三线互联网 34 | 35 | * 完美世界 (成都)游戏 36 | * 聚美优品 (成都) 37 | * 陌陌 (成都) 38 | * 爱奇艺(成都) 39 | 40 | ## 外企互联网 41 | 42 | * NAVER China (成都)搜索引擎公司,主要针对韩国市场 43 | 44 | ## 创业公司 45 | 46 | * tap4fun(总部)游戏 47 | * 趣乐多(总部)游戏 48 | * 天上友嘉(总部)游戏 49 | * 三七互娱(成都)游戏 50 | * 咕咚(总部)智能运动 51 | * 百词斩(总部)在线教育 52 | * 晓多科技(总部)AI方向 53 | * 萌想科技(总部)实习僧 54 | * Camera360(总部)移动影像社区 55 | * 医联 (总部)医疗解决方案提供商 56 | * 小明太极 (总部)原创漫画文娱内容网站以及相关APP 57 | * 小鸡叫叫(总部)致力于儿童教育的智慧解决方案 58 | 59 | 60 | ## AI独角兽公司 61 | 62 | * 科大讯飞(成都) 63 | * 商汤(成都) 64 | 65 | ## 总结 66 | 67 | 可以看出成都相对一线城市的互联网氛围确实差了很多。**但是!成都已经是在内陆城市中甚至二线城市中的佼佼者了!** 68 | 69 | 从公司的情况上也可以看出:**成都互联网行业目前的名片是“游戏”**,腾讯、完美世界等大厂,还有无数小厂都在成都搞游戏,可能成都的天然属性就是娱乐,这里是游戏的沃土吧。 70 | 71 | 相信大家如果在一些招聘平台上去搜,其实很多公司都在成都,但都是把客服之类的工作安排在成都,而我在列举的时候尽量把研发相关在成都的公司列出来,这样对大家更有帮助。 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | ----------------------- 80 |
81 | -------------------------------------------------------------------------------- /problems/知识星球精选/大厂新人培养体系.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 | 6 | # 大厂的新人培养体系是什么样的 7 | 8 | 之前我一直在[知识星球](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ)和大家讲,能进大厂一定要进大厂,大厂有比较好的培养体系。 9 | 10 | 也有录友在星球里问我,究竟培养体系应该是什么样的呢? 大厂都会这么培养新人么? 11 | 12 | ![](https://code-thinking-1253855093.cos.ap-guangzhou.myqcloud.com/pics/20210717173307.png) 13 | 14 | 其实大厂部门也是非常多,不同的领导对待新人的态度也是不一样的。 15 | 16 | 就拿腾讯来说,腾讯里面 上千个部门,基本就是上千个小公司,只不过外面披一个腾讯的壳子,每个小公司的leader风格截然不同。 17 | 18 | 赶上什么样的领导了,这就看命运了。 19 | 20 | **只能说进大厂,大概率会有一个比较好的培养体系**。 21 | 22 | 那么好的培养体系是什么呢? 23 | 24 | 要从两个方面来说: 25 | 26 | * 给你详细的学习路线(自我技术提升) 27 | * 给你有产出的活(用来晋升) 28 | 29 | ## 详细的学习路线 30 | 31 | 关于详细的学习路线,一般大厂入职之后配有导师的,导师给你安排的每一个功能,应该带你熟悉整个研发的流程。 32 | 33 | 一个功能的开发,需要经历如下几步: 34 | 35 | 1. 看需求文档,确定需求 36 | 2. 这个需求包含了哪些功能 37 | 3. 有哪些难点 38 | 4. 后台架构是什么样的(要有架构图) 39 | 5. 定协议(前后台一起商量),服务与服务之间的,后台与客户端之间的 40 | 6. 设计数据结构+算法=程序 41 | 7. 预估一下容量(各种资源例如带宽,存储,CPU等等) 42 | 8. 考虑一下部署(安全性,容灾,可伸缩性。。。。) 43 | 9. 设计评审 44 | (上面过程都是在分析) 45 | 10. 编码 46 | 11. 自测 47 | 12. 联调 48 | 13. 交给测试 49 | 14. 代码review 50 | 15. 合入 51 | 16. 发布 52 | 53 | 可以看出来,写代码仅仅是 其中的一小步。导师应该带你走一遍完整的开发流程,然后告诉一些注意事项,**这样为自己程序员生涯打好基础**。 54 | 55 | 可能有的同学会感觉:我就开发一个小功能,哪用得着这么多步骤,一把梭哈,直接代码写完。 56 | 57 | 哈哈,这么想的同学一般是没有参与过大型且流程规范的项目开发。互联网千万级用户的项目,几十上百人一起开发是需要规范的,**所以上面我说的每一步都很重要!** 58 | 59 | ## 有产出的活 60 | 61 | 初入职场的同学,可能都非常在意能不能学到东西,也就是自我技术提升,往往忽视了你干的活,是否有产出,能不能用来晋升。 62 | 63 | 这里就是很多所谓的“套路”,老司机一般挑的活符合如下几点: 64 | 65 | * 非常规整(周边没有烂糟的额外工作,例如还要开发各种小工具之类的) 66 | * 独立模块(不需要和其他人扯皮,省事) 67 | * 对项目组很重要(既有技术难点,又没有大量的业务增删改查) 68 | * 风险系数比较低(上线出问题,锅甩不到他这里) 69 | 70 | 这种活就是好活,用来晋升的利器,而且干着也舒服。 71 | 72 | 但一个项目,一定会有大量需要打杂的活,写各种脚本,各种处理数据,然后看各种问题,整理文章,汇报,开发边缘工具等等。 73 | 74 | 新人一般进来都是先打杂的,**但如果领导确实是细心培养你,还是额外给你一个小模块,让你做好,这个小模块就是让你用来晋升的或者转正的**。 75 | 76 | 这个建议不仅适用于实习生,对于初入职场的同学也很用帮助,这个部门是不是有在培养你,老司机一眼就能看出来,只不过新人可能自己很难发现。 77 | 78 | 所以需要过来人点拨一下,大家就知道自己现在的处境了。 79 | 80 | 希望对大家求职和工作有所帮助! 81 | 82 | -------------------------------------------------------------------------------- /problems/知识星球精选/关于提前批的一些建议.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 | 6 | # 秋招和提前批都越来越提前了.... 7 | 8 | 正在准备秋招的录友,可能都感受到了,现在的秋招越来越提前了.... 9 | 10 | 以前提前批,都是 8月份,8月份中序左右,而不少大厂现在就已经提前批了。 11 | 12 | 不少录友在 公众号留言,和[知识星球](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ)里,表示提前批来的还是有点快。 13 | 14 | ![](https://code-thinking-1253855093.cos.ap-guangzhou.myqcloud.com/pics/20210618162214.png) 15 | 16 | 还没有把刷题攻略刷完的录友,要尽快刷完,至少先刷一遍,了解相关题型。 17 | 18 | 星球里,也有一些录友感受到了提前批的突如其来。 19 | 20 | ![](https://code-thinking-1253855093.cos.ap-guangzhou.myqcloud.com/pics/20210619190111.png) 21 | 22 | 目前已经开始的提前批有 vivo, tp-link,京东,百度..... 23 | 24 | ![](https://code-thinking-1253855093.cos.ap-guangzhou.myqcloud.com/pics/20210619190022.png) 25 | 26 | 27 | 有的录友已经明显紧张起来了。 28 | 29 | ![](https://code-thinking-1253855093.cos.ap-guangzhou.myqcloud.com/pics/20210619190354.png) 30 | 31 | 其实这才刚刚开始,等 7月份 以后,又是铺天盖地的信息,大家更没心情静下心来看书了。 32 | 33 | 34 | # 关于提前批的一点小建议 35 | 36 | **首先我们要知道为什么有提前批?** 37 | 38 | 提前批不是大厂们呆着没事闲着多给我们一次面试机会,**而是提前抢优秀毕业生**,这一点大家一定要明确。 39 | 40 | 41 | 了解了为什么有提前批,这样我们就有正确的心态面对它了。 42 | 43 | 如果没有准备好,或者自己定位因为不是 “优秀毕业生”,先不要碰提前提。 44 | 45 | 当然可以先面一些自己不想去的公司的提前批,用来练手。 46 | 47 | 至于对于自己心仪的公司,如果盲目参加提前批,首先会打乱自己的复习计划,和心态,然后就是提前批挂了后台都是有记录的。 48 | 49 | 只要是大厂的内部信息化做的比较完善,提前批挂了,是一定会记录的。 50 | 51 | **那么提前批有没有影响呢?** 52 | 53 | 很多招聘宣传的时候说,提前批挂了对秋招没影响,确实在一定程度上没影响,因为提前批挂了,依然可以投递秋招。 54 | 55 | 然后秋招面试的时候,面试官在不在意你的提前批成绩,就是另一回事了。 56 | 57 | 我之前内推了一些录友面试腾讯微信支付的部门,面试官和我很熟悉,我最近还和他吃了饭,聊一聊我内推的同学,他说看后台记录有些同学都投过好几次了,他看了之前面试结果的评价之后,就直接pass了。 58 | 59 | 所以大家可能要想好一个回答,就是面试官可能问:你的提前批为什么挂了? 60 | 61 | 而且提前批挂了,都是有当时面试官评语的,如果7月份提前批面试,面试官评价:这位候选人基础不行。 62 | 63 | 秋招的时候,面试官也不会相信,一两个月能把基础补上来了。 即使你的基础其实没问题,只不过恰巧面试中的几个问题没答好而已。 64 | 65 | 66 | 对于技术能力确实强的同学,我建议全力以赴准备提前批面试,因为提前批要求就比较高,很容易谈sp offer。而且现在就拿到了大厂offer,比找实习还香。 67 | 68 | 如果没准备好的同学,建议不要让提前批打乱阵脚,有计划的巩固基础,准备秋招。或者先拿自己不想去的公司的提前批练手。 69 | 70 | 71 | 好了,说了这么多,希望对录友们有所帮助,加油💪 72 | 73 | -------------------------------------------------------------------------------- /problems/知识星球精选/秋招开奖.md: -------------------------------------------------------------------------------- 1 | 2 |

3 | 4 | 5 | 6 | 7 | # 开奖 8 | 9 | 最近秋招的录友已经陆续开奖了,同时开奖多少,也是offer选择的一个重要因素,毕竟谁能和钱过意不去呢。 10 | 11 | [知识星球](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ)里这位录友拿到的百度offer薪资确实很高 12 | 13 | ![](https://code-thinking-1253855093.file.myqcloud.com/pics/20211023102430.png) 14 | 15 | 以下是我的回答: 16 | 17 | -------------- 18 | 19 | 百度给你的这个薪资很不错了,百度一向是大厂里最扣的那个,能给这个价位,说明 面试官对你很满意。 20 | 21 | 语言方面你不用过于纠结,其实学什么语言最终都是为了赚钱是吧,钱给到位了,写啥不都一样么。 22 | 23 | 而且如果后面php 要转go的话,你就还很多锻炼的机会,对你晋升十分有好处,php转go,就是把已有的后端代码全部重写,相当于是重构,就是很多工作可以做。 24 | 25 | **程序员最喜欢的就是重构**,重构既能提升技术,又能向上邀功(**可以理解就是容易晋升**)。 26 | 27 | 如果是稳定的业务,进去大概率是打杂的,因为没有那么多代码可写,进去就改改bug,写写脚本分析分析日志,之类的,总之不会接触到核心代码,没有机会,也没有必要。 28 | 29 | 但如果稳定的业务 代码要重构,就有机会可以读一读核心代码,分析哪里设计的不好,重写一遍,那就可以大展宏图。 30 | 31 | 这就是为什么程序员都喜欢重构。 32 | 33 | 字节的话 后端-系统架构,这个岗位是可以的,但具体什么部门,具体做什么就不太清楚了,至于你说的边缘部门,如果这个部门就叫做系统架构部的话,不可能是边缘部门。系统架构部门还是挺重要的。 34 | 35 | 但如果 字节和百度选的话,我还是倾向于百度。 百度对新人培养还很到位的,比字节强多了。 36 | 37 | 滴滴就不考虑了, 华为 2012实验室中央软件院,其实是不错的,适合好好搞技术,但关于 多媒体开发 这块 要看具体工作了。 38 | 2012 一般薪资开的不高,毕竟不是华为的业务部门。 39 | 40 | 如果百度过几天逼签的话,就签了吧,挺香的,总包都40w+了,百度一向是很抠的,**这个价位,百度是下血本了**。 41 | 42 | 如果还能拖,就等 字节 和 华为开奖,如果能开到 50w+,那就考虑考虑。 43 | 44 | 如果薪资差不多,就百度吧。 45 | 46 | 47 | ------------- 48 | 49 | 这位录友最后也决定签百度了。 50 | 51 | ![](https://code-thinking-1253855093.file.myqcloud.com/pics/20211021234705.png) 52 | 53 | 大家也注意到,这位录友是把《代码随想录》刷了两篇,这里我也是推荐大家至少要把 《代码随想录》上的题目刷两遍,才能真正的掌握我讲解的内容,第一遍大家可能就是力扣提交通过了,然后这道题目就过了,没有深入去思考,也没有深入去看我的题解。 54 | 55 | 但第二遍的时候,就可以深入思考 上一道题目与本题之间的联系,动态规划或者二叉树的题目套路 等等了。 56 | 57 | 58 | 还有这位录友在星球里提到,用了我推荐的项目,其实这就是这个:[基于跳表的轻量级KV存储引擎](https://mp.weixin.qq.com/s/i3vJd0nPqQFyLRH9Px84YA) 59 | 60 | ![](https://code-thinking-1253855093.file.myqcloud.com/pics/20211023103749.png) 61 | 62 | 这个项目是我18年的时候,业余时间写的,大家如果按照我的代码来,从代码质量到结构设计,绝对是可以拿得出手的。 63 | 64 | 但我没有写这个项目的详细教程,很多基础不太好的录友可能看着有点费劲,后面我会在B站上出一期详细的讲解视频,公众号也会同步文字版本。 65 | 66 | -------------------------------------------------------------------------------- /problems/知识星球精选/备战2022届秋招.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 | 6 | # 要开始准备2022届的秋招了 7 | 8 | 在[知识星球](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ)里准备秋招的录友还真不少,也会回答过不少关于秋招的问题。 9 | 10 | ![](https://img-blog.csdnimg.cn/20210507195443924.png) 11 | 12 | 能感觉出来慌,不止这一位提问题的录友,很多同学都是这样,就是感觉一天天过的很快,也没干什么事情,然后心里就一直恐慌。 13 | 14 | 其实**慌主要是因为没有计划**,每天没有目的,然后一天一天的过,秋招越来越近,自然慌的很。 15 | 16 | 我在这篇里系统性的解答了实习相关的问题,[关于实习,大家可能有点迷茫!](https://mp.weixin.qq.com/s/xcxzi7c78kQGjvZ8hh7taA),也提到了 一般秋招8月份就要正式开始了,那时候各种提前批,面试小道消息,甚至身边一些同学已经拿到了offer,恐怕已经没有时间静下心好好学习了。 17 | 18 | 所以从现在看是满打满算,还有三个月的准备时间,如果利用好还是挺充足的,不要每天在把时间浪费在各种无聊的活动上。 19 | 20 | 这里我来列举一下,此时大家应该明确哪些事情: 21 | 22 | ## 确定自己要面试的岗位 23 | 24 | 说道选择哪些岗位,一般的回答都是:选择自己感兴趣的呗,兴趣是最好的老师之类的balabala。 25 | 26 | 但我能亲身体会到,目前咱们的教育环境 也不可能说培养出什么 自己真正的兴趣,在大街上随便问一个人你的兴趣是什么? 基本回答都是:吃喝玩睡呗,还能有啥兴趣。 27 | 28 | 所以务实的建议是:现在去各大公司校招招聘官网 把所有的岗位都看一看,看看都有哪些要求,结合目前自己的经历和已经掌握的内容,看看哪些岗位可能最接近,然后再问问师兄师姐 这个岗位或者公司如何,最后后就把自己的目标岗位定下来了。 29 | 30 | 也有很多录友在星球里问我关于一些公司,岗位前景之类的问题,我都会给出相应的建议,这也是我工作过程中接触过了解过的。后面我也把部分内容整理一下,在公众号分享一下。 31 | 32 | 这样接下来的时间就是全身心去准备这个岗位所需要的技能。 33 | 34 | **不少同学在秋招的时候,试试算法岗感觉也行,投投前端感觉也行,尝试后端也不是不可以,甚至再面面产品经理**。 35 | 36 | **这样在秋招的时候就很被动了**,哪个岗位都没准备好,哪个岗位还都想试试,大概率是最后都没面上的。 37 | 38 | 所以现在就要把自己的目标岗位锁定了。 不同岗位之间 要求还是不一样的。 大家去看看招聘官网的要求就可以了。 39 | 40 | ## 制定学习计划 41 | 42 | 知道自己的目标岗位了,也知道岗位的要求了,剩下的就是制定详细的计划。 43 | 44 | * 编程语言 45 | * 计算机基础(操作系统,网络,数据库、设计模式) 46 | * linux相关(客户端岗位应该不需要) 47 | * 项目 48 | * 准备自己的博客,github 49 | 50 | 这几块按照岗位要求,8月份应该学会哪些内容,需要看哪些书等等。 51 | 52 | 然后以八月份以deadline开始倒推,每个月应该学哪些,每周应该学哪些,每天应该看那些。 53 | 54 | 把这些都明确了,心里就不慌了,也不会每天浪费大量宝贵的时间。 55 | 56 | 星球里的录友每天都在坚持打卡,总结自己今天学习的内容,这样就很好,把自己每天学习进度量化。 57 | 58 | 这样每天过的就很扎实。而且每天的打卡星球里录友和我都可以看到,我也会及时评论评论,大家也相互监督。 59 | 60 | 给大家看一位录友在星球里的总结: 61 | 62 | ![](https://img-blog.csdnimg.cn/20210507204017952.png) 63 | 64 | 大家平时的话,也要养成这种总结的习惯,只有及时总结把自己学过的内容积累下来,才能把时间沉淀下来,要不然就是一边学一边忘的节奏了。 65 | 66 | **其实这种习惯,无论是秋招,还是准备跳槽,还是平时工作积累,都非常总要!** 67 | 68 | -------------------------------------------------------------------------------- /problems/知识星球精选/刷题攻略要刷两遍.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 | 6 | # 代码随想录上的题目最好刷两遍以上 7 | 8 | 今天秋招可能要提前很多,往年9月份开始秋招,今天可能9月份就已经结束了,所以 正在准备秋招的录友,还是要抓紧时间了。。 9 | 10 | 星球里已经有录友的给出了关于秋招提前的信息 11 | 12 | ![](https://code-thinking-1253855093.file.myqcloud.com/pics/20210801104138.png) 13 | 14 | 那么在正式秋招之前,大家在准备算法,代码随想录上的题目 应该刷几篇呢? 15 | 16 | **至少刷两遍,只刷一遍是不够的**。 17 | 18 | 只刷一遍基本就会忘,而且关键方法论理解的也不到位,对递归三部曲,回溯三部曲,动规五部曲,只掌握了简单招式,而没有理解真正精髓。 19 | 20 | 拿到最简单的反转链表来说,只做一遍,下次面试出现基本还是做不出来。 21 | 22 | 这也是星球里 录友们的 多么痛的领悟! 23 | 24 | ![](https://code-thinking-1253855093.file.myqcloud.com/pics/20210731183247.png) 25 | 26 | **等大家刷第二遍的时候,才能找到触类旁通的感觉!** 27 | 28 | 第三遍基本就得心应手了。 29 | 30 | 在[「代码随想录」知识星球](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ)中,我都是强调大家要至少刷两遍,有时间的话刷三遍, 31 | 32 | 可以看看星球里录友们的打卡: 33 | 34 | ![](https://code-thinking-1253855093.cos.ap-guangzhou.myqcloud.com/pics/20210701122522.png) 35 | 36 | ![](https://code-thinking-1253855093.cos.ap-guangzhou.myqcloud.com/pics/20210701122422.png) 37 | 38 | ![](https://code-thinking-1253855093.cos.ap-guangzhou.myqcloud.com/pics/20210701122313.png) 39 | 40 | 有的录友已经开始三刷: 41 | 42 | ![](https://code-thinking-1253855093.file.myqcloud.com/pics/20210727234031.png) 43 | 44 | 45 | 我为什么鼓励大家有时间的话,多刷几遍呢,首先这里的题目都是经典题目,而且在面试汇总也是频频出现, 46 | 47 | 下面也是星球里的录友总结的面经: 48 | 49 | ![](https://code-thinking-1253855093.cos.ap-guangzhou.myqcloud.com/pics/20210701121136.png) 50 | 51 | ![](https://code-thinking-1253855093.cos.ap-guangzhou.myqcloud.com/pics/20210723125816.png) 52 | 53 | 54 | ## 那么已有的题目刷完了,可以刷些什么呢? 55 | 56 | 我在Github上也做了一些题目的补充,在[上榜之后,都有哪些变化?](https://mp.weixin.qq.com/s/VJBV0qSBthjnbbmW-lctLA)说到了。 57 | 58 | 对于面试来说除了「代码随想录」上的题目,再了解一下:排序系列,简单图论(深搜,广搜,最小生成树,最短路径等),高级数据结构:并查集,字典树(了解一下),之后就差不多了。随便在leetcode找一些题目保持手感,题量至少300+,会稳一点。 59 | 60 | 关于深搜和广搜,其实深度优先搜索,我在二叉树的专题中讲解递归遍历,和回溯算法中 都讲了。 61 | 62 | 广度优先搜索,在二叉树树的层序遍历也讲了。 63 | 64 | 而图论中主要是在邻接表上进行的深搜和广搜。 65 | 66 | 面试中还是很少会考察图论,因为图论的代码量往往比较大,不适合在面试中考察,**面试中出现题目概率最大的是二叉树,回溯算法和动态规划!** 67 | 68 | -------------------------------------------------------------------------------- /problems/前序/深圳互联网公司总结.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 | 6 |

7 |

欢迎大家参与本项目,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!

8 | 9 | 10 | # 深圳互联网公司总结 11 | 12 | **个人总结难免有所疏忽,欢迎大家补充,公司好坏没有排名哈!** 13 | 14 | ## 一线互联网 15 | 16 | * 腾讯(总部深圳) 17 | * 百度(深圳) 18 | * 阿里(深圳) 19 | * 字节跳动(深圳) 20 | 21 | ## 硬件巨头 (有软件/互联网业务) 22 | 23 | * 华为(总部深圳) 24 | * 中兴(总部深圳) 25 | * 海能达(总部深圳) 26 | * oppo(总部深圳) 27 | * vivo(总部深圳) 28 | * 深信服(总部深圳) 29 | * 大疆(总部深圳,无人机巨头) 30 | * 一加手机(总部深圳) 31 | * 柔宇科技(国内领先的柔性屏幕制造商,最近正在准备上市) 32 | 33 | ## 二线大厂 34 | 35 | * 快手(深圳) 36 | * 京东(深圳) 37 | * 顺丰(总部深圳) 38 | 39 | ## 三线大厂 40 | 41 | * 富途证券(2020年成功赴美上市,主要经营港股美股) 42 | * 微众银行(总部深圳) 43 | * 招银科技(总部深圳) 44 | * 平安系列(平安科技、平安寿险、平安产险、平安金融、平安好医生等) 45 | * Shopee(东南亚最大的电商平台,最近发展势头非常强劲) 46 | * 有赞(深圳) 47 | * 迅雷(总部深圳) 48 | * 金蝶(总部深圳) 49 | * 随手记(总部深圳) 50 | 51 | ## AI独角兽公司 52 | 53 | * 商汤科技(人工智能领域的独角兽) 54 | * 追一科技(一家企业级智能服务AI公司) 55 | * 超多维科技 (计算机视觉、裸眼3D) 56 | * 优必选科技 (智能机器人、人脸识别) 57 | 58 | ## 明星创业公司 59 | 60 | * 丰巢科技(让生活更简单) 61 | * 人人都是产品经理(全球领先的产品经理和运营人 学习、交流、分享平台) 62 | * 大丰收(综合农业互联网服务平台) 63 | * 小鹅通(专注新教育的技术服务商) 64 | * 货拉拉(拉货就找货拉拉) 65 | * 编程猫(少儿编程教育头部企业) 66 | * HelloTalk(全球最大的语言学习社交社区) 67 | * 大宇无限( 拥有SnapTube, Lark Player 等多款广受海外新兴市场用户欢迎的产品) 68 | * 知识星球(深圳大成天下公司出品) 69 | * XMind(隶属深圳市爱思软件技术有限公司,思维导图软件) 70 | * 小赢科技(以技术重塑人类的金融体验) 71 | 72 | ## 其他行业(有软件/互联网业务) 73 | 74 | * 三大电信运营商:中国移动、中国电信、中国联通 75 | * 房产企业:恒大、万科 76 | * 中信深圳 77 | * 广发证券,深交所 78 | * 珍爱网(珍爱网是国内知名的婚恋服务网站之一) 79 | 80 | 81 | 82 | 83 | 84 | ----------------------- 85 |
86 | -------------------------------------------------------------------------------- /problems/知识星球精选/专业技能可以这么写.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 | 6 | 7 | 8 | # 你简历里的「专业技能」写的够专业么? 9 | 10 | 11 | 其实我几乎每天都要看一些简历,有一些写的不错的,我都会在[知识星球](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ)里分享一下。 12 | ![](https://code-thinking-1253855093.cos.ap-guangzhou.myqcloud.com/pics/20210626172902.png) 13 | 14 | 这次呢,我再专门说一说简历中的【专业技能】这一栏应该怎么写。 15 | 16 | 很多同学【专业技能】这块写的很少,其实不是掌握的少,而是没有表达出来。 17 | 18 | 例如有的同学这么写: 19 | 20 | 21 | ![](https://code-thinking-1253855093.cos.ap-guangzhou.myqcloud.com/pics/20210626173915.png) 22 | 23 | --------------------- 24 | 25 | ![](https://code-thinking-1253855093.cos.ap-guangzhou.myqcloud.com/pics/20210626173940.png) 26 | 27 | -------------------- 28 | 29 | ![](https://code-thinking-1253855093.cos.ap-guangzhou.myqcloud.com/pics/20210626174018.png) 30 | 31 | ------------------- 32 | 33 | ![](https://code-thinking-1253855093.cos.ap-guangzhou.myqcloud.com/pics/20210626174809.png) 34 | 35 | 36 | 这些【专业技能】都写的很少,其实是可以在丰富一些的。 37 | 38 | 我来给大家拓展一下、 39 | 40 | 41 | * 熟练C++,(列举C++的若干知识点),了解 Java,python,go (适当补充对这些语言的理解) 42 | * 熟悉常见设计模式(例句一些设计模式) 43 | * 熟悉linux操作系统vim开发环境,(列举网络编程相关知识,例如epoll,socket等等) 44 | * 熟悉网络,(列举网络协议相关考点,tcp/ip,http, https, 三次,四次握手,流量控制等等) 45 | * 数量掌握数据结构与算法(列举常用算法,最好搞透一个算法,说对该算法有独到见解) 46 | * 数量使用Git,等版本控制 47 | * 以上为公共写法,下面可以在补充自己的其他领域的内容 48 | 49 | 50 | 针对以上这个模板, 再来补充相关内容: 51 | 52 | 1. 熟悉C/C++,熟练使用C的指针应用及内存管理,C++的封装继承多态,STL常用容器,C++11常用特性(智能指针等) ,了解 Python,Gtest等。 53 | 2. 熟悉常用设计模式(单例模式,工厂模式等) 54 | 3. 熟悉Linux下vim开发环境,了解网络编程,IO多路复用,epoll等等。 55 | 4. 熟悉OSI五层网络模型,熟悉TCP/IP,UDP,HTTP/HTTPS,DNS等网络协议,熟悉TCP三次握手,四次挥手,流量控制,拥塞控制等手段。 56 | 5. 熟悉常用的数据结构(链表、栈、队列、二叉树等),熟练使用排序,贪心,动态规划等算法。 57 | 6. 熟悉使用Git,vscode工具使用。 58 | 59 | 但需要注意的是,这里写的点,自己一定要熟练掌握,因为简历上写的,面试官一定会问。 60 | 61 | 这样有一个好处,就是 **缩小面试官的问题范围**, 只要简历上写的,你都准备好了,那么简历上的知识点面试官一定会问,这样你就掌握了主动权。 62 | 63 | 举一个例子,如果简历上直写:熟悉C++。其他都没介绍,那么面试官指定围绕C++漫天遍野的问起来了,你也猜不透面试官想问啥。 64 | 65 | 如果简历写熟悉C/C++,熟练使用C的指针应用及内存管理,C++的封装继承多态,STL常用容器,C++11常用特性(智能指针等)。那么面试官基本上只会问,内存管理,多态,STL和C++11的一些特性, **这样你就把面试官的问题都圈在可控范围内**,从而掌握主动权! 66 | 67 | 这一点很重要,希望大家要有这个思路,去写自己的简历。 68 | 69 | 70 | -------------------------------------------------------------------------------- /problems/知识星球精选/天下乌鸦一般黑.md: -------------------------------------------------------------------------------- 1 | 2 |

3 | 4 | 5 | 6 | 7 | # 天下乌鸦一般黑,哪家没有PUA? 8 | 9 | 相信大家应该经常在 各大论坛啊之类的 看到对各个互联网公司的评价,有风评好的,也有风评不好的。 10 | 11 | 在[知识星球](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ)里有录友问我这样一个问题: 12 | 13 | ![](https://code-thinking-1253855093.file.myqcloud.com/pics/20211004095707.png) 14 | 15 | 这位录友,拿了阿里云,腾讯,百度,shopee的意向书,可以确是收割机了,但如果还没有进入职场,还容易被网上这些风评误导。 16 | 17 | 卡哥来客观的分析一下,如何看到这些网上对公司的评论。 18 | 19 | 脉脉,知乎上喷阿里,百度的 都比较多。喷腾讯的确实少一些。 20 | 21 | **只能说腾讯的舆论控制相对比较好**,在加上职能体系的人文关怀比较到位(公仔,各种活动,逢年过节小礼品之类的)。 22 | 23 | 但**天下乌鸦一般黑**,腾讯的职场PUA,一点都不比阿里的少,各种套路 ,阿里有的,腾讯都有,还有什么各种花边吃瓜新闻,在腾讯内网特别多。 24 | 25 | 但这些都在公司内网传播,很少传出去。 这就是腾讯厉害所在了。 26 | 27 | 其实我们在选择公司的时候,**主要是看岗位,看业务,看发展**,至于 有没有PUA之类的,只能说**有人的地方就有江湖**,腾讯人 就比 阿里人 就更正直么? 28 | 29 | 相信大家都参加过面试。招聘的时候,几个小时的面试能看出人品么?对吧。 30 | 31 | 各种新人背锅,末尾淘汰,PUA,阿里有的,腾讯都有。 所以大家求职的时候不用在乎这些风评。 32 | 33 | 至于这种锅和套路 能不能落到自己的头上,就要看碰到了什么样的直属领导了。 34 | 35 | 例如两位同学去了同一家公司,同一个事业群,同一个部门,同一个项目组,只是在两个不同的领导下干活,其区别都可以一个天上,一个地上。 36 | 37 | 有的录友 可能对职场套路不太了解,或者 初入职场比较顺利,没有感受过什么套路。 38 | 39 | 这里卡哥给大家随便说一个,例如,一个项目组,有前端组和后端组,分别是两个老大,有一个需求,要开发一个功能,这个功能本来前端就可以独立完成的,但上线可能会有风险,保护自己手下的前端领导,就会让前端同学和后端的同学一起实现这个功能,也就是前端实现一部分,后端也要做一部分数据处理,前端展示就可以了。 40 | 41 | 为什么这么安排呢? 42 | 43 | 因为一旦上线出问题了,就是前端和后端一起背锅,这样前端同学压力就小很多了。 44 | 45 | 而整个需求安排,前端同学其实并不知道 自己的风险,其实是领导保护了他。 46 | 47 | 那么 不保守下手的领导,当然就啥也不说了,让你一个人把这个功能做了,上线没出问题 那还算万事大吉,一旦出问题,那年底考核是不是就要背一个指标了。 48 | 49 | 所以不要感觉程序员的工作环境很单纯,其实套路多得很,还是那句话:**有人的地方就有江湖**,不区分公司的。 50 | 51 | 只能说 业务发展越好的部门,套路相对来说少一点,毕竟高速发展可以掩盖很多问题。 52 | 53 | **所以遇到什么样的直属领导非常非常的重要**,但这又是我们决定不了的。 所以这都看缘分(运气)了。 54 | 55 | 有的同学毕业在大厂顺风顺水,除了自己努力外(而大家谁又不努力呢?),更重要的是遇到了好领导。 56 | 57 | 但有的同学同样进大厂,发展就很差,而且没人给他指引一些部门潜在的规则,那就难免会撞坑。 58 | 59 | 未必是他不够努力,不够聪明,不会沟通,可能恰巧 部门效益不好,部门考核就差,领导一般不会让老人背锅,毕竟系统的bug都是老人写的,老人都走了,谁来修bug呢(人间真实)。 60 | 61 | 那领导就拿他这个新人开刀了呗。 62 | 63 | 所以,**同样是进大厂,发展好的同学 不用过于优越感,感觉是自己能力多强,其实大概率是赶上了 好部门好领导,发展不好的同学也不要 自责自己能力不行,甚至开始自卑,大概率是运气不太好而已**。 64 | 65 | 那么是 发展好坏全看运气了么,当然不是! 66 | 67 | 重要是 遇到挫折(背锅,绩效不好,甚至被开除),不要自卑,不要放弃,相信自己,只要把时间拉长,5-10年的时间,**真正努力的人,发展都不错!** 68 | 69 | 卡哥希望录友们都有好的发展,加油💪 70 | 71 | 72 | -------------------------------------------------------------------------------- /problems/前序/杭州互联网公司总结.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 | 6 |

7 |

欢迎大家参与本项目,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!

8 | 9 | 10 | 11 | # 杭州互联网公司总结 12 | 13 | **个人总结难免有所疏忽,欢迎大家补充,公司好坏没有排名哈!** 14 | 15 | ## 一线互联网 16 | 17 | * 阿里巴巴(总部) 18 | * 蚂蚁金服(总部)阿里旗下 19 | * 阿里云(总部)阿里旗下 20 | * 网易(杭州) 网易云音乐 21 | * 字节跳动(杭州)抖音分部 22 | 23 | ## 外企 24 | 25 | * ZOOM (杭州研发中心)全球知名云视频会议服务提供商 26 | * infosys(杭州)印度公司,据说工资相对不高 27 | * 思科(杭州) 28 | 29 | ## 二线互联网 30 | 31 | * 滴滴(杭州) 32 | * 快手(杭州) 33 | 34 | ## 硬件巨头 (有软件/互联网业务) 35 | 36 | * 海康威视(总部)安防三巨头 37 | * 浙江大华(总部)安防三巨头 38 | * 杭州宇视(总部) 安防三巨头 39 | * 萤石 40 | * 华为(杭州) 41 | * vivo(杭州) 42 | * oppo(杭州) 43 | * 魅族(杭州) 44 | 45 | ## 三线互联网 46 | 47 | * 蘑菇街(总部)女性消费者的电子商务网站 48 | * 有赞(总部)帮助商家进行网上开店、社交营销 49 | * 菜鸟网络(杭州) 50 | * 花瓣网(总部)图片素材领导者 51 | * 兑吧(总部)用户运营服务平台 52 | * 同花顺(总部)网上股票证券交易分析软件 53 | * 51信用卡(总部)信用卡管理 54 | * 虾米(总部)已被阿里收购 55 | * 曹操出行(总部) 56 | * 口碑网 (总部) 57 | 58 | ## AI独角兽公司 59 | 60 | * 旷视科技(杭州) 61 | * 商汤(杭州) 62 | 63 | ## 创业公司 64 | 65 | * e签宝(总部)做电子签名 66 | * 婚礼纪(总部)好多结婚的朋友都用 67 | * 大搜车(总部)中国领先的汽车交易服务供应商 68 | * 二更(总部)自媒体 69 | * 丁香园(总部) 70 | 71 | ## 总结 72 | 73 | 杭州距离上海非常近,难免不了和上海做对比,上海是金融之都,如果看了[上海有这些互联网公司,你都知道么?](https://programmercarl.com/前序/上海互联网公司总结.html)就会发现上海互联网也是仅次于北京的。 74 | 75 | 而杭州是阿里的大本营,到处都有阿里的影子,虽然有网易在,但是也基本是盖过去了,很多中小公司也都是阿里某某高管出来创业的。 76 | 77 | 杭州的阿里带动了杭州的电子商务领域热度非常高,如果你想做电商想做直播带货想做互联网营销,杭州都是圣地! 78 | 79 | 如果要是写代码的话,每年各种节日促销,加班996应该是常态,电商公司基本都是这样,当然如果赶上一个好领导的话,回报也是很丰厚的。 80 | 81 | 「代码随想录」一直都是干活满满,值得介绍给每一位学习算法的同学! 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | ----------------------- 90 |
91 | -------------------------------------------------------------------------------- /problems/知识星球精选/不少录友想放弃秋招.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 | 6 | # 不少录友想放弃秋招了..... 7 | 8 | 马上就要九月份了,互联网大厂的秋招的序幕早已拉开。 9 | 10 | 发现[知识星球](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ)里有一部分录友想放弃秋招,直接准备明年的春招,估计关注公众号的录友也有不少有这种想法的。 11 | 12 | ![](https://code-thinking-1253855093.file.myqcloud.com/pics/20210813103515.png) 13 | 14 | 一般有这种想法的录友都是 **之前没有准备好,或者是总感觉时间赶趟赶趟,然后突然间 发现时间不赶趟了。。。** 15 | 16 | 也有一些感觉自己没有实习经历,简历上也没什么好写,想下半年去找一找实习,不去秋招,然后直接准备春招。 17 | 18 | **对于这种情况,我的建议依然要冲刺秋招!** 19 | 20 | # 把秋招当做最后的机会 21 | 22 | **等到春招的时候,可以选岗位已经很少了,各个大厂几乎都招满了**。 23 | 24 | 而且就算秋招没找到好工作,一般 11月份左右,一些大厂还会有补招,腾讯就经常补招。 25 | 26 | 补招的情况是就是腾讯发出了 offer,有的候选人 选择违约,不来了,那么腾讯就需要补招,把人数凑齐。 27 | 28 | 可能有录友想,谁居然连腾讯的offer都拒绝呢? 29 | 30 | 其实挺多的,例如:有其他大厂的核心部门offer,父母给安排了 国企、央企 的核心岗位,或者有的选择 读博了之类的,导师毕业能给安排留校 或者去其他高校任教。 31 | 32 | 所以几乎每年,腾讯都要补招,其他大厂也会有补招,一般是11月份,所以就算秋招没拿到大厂offer,依然有机会! 33 | 34 | 话再说回来,面试其实也很看缘分,**永远没有真正准备好的时候,知识一直都学不完**。 35 | 36 | 所以 **把秋招当做最后的机会,就算秋招没找到,也可以在冲春招,而不是 直接放弃秋招**。 37 | 38 | 39 | # 放弃秋招,对心态的影响 40 | 41 | 如果直接放弃秋招,等 今年 10月份,身边同学都找到工作了,那时候的场面就是歌舞升平,大家天天吃喝玩乐。 42 | 43 | 见面打会招呼就问:你去哪了,你签哪了? 44 | 45 | 那时候如果自己还没有面试,还在准备面试,此时自己心里阴影面积有多大,甚至会影响春招找工作。 46 | 47 | # 面试要趁早准备 48 | 49 | 每年这时候,都会有同学后悔,我怎么就没早点准备,就感觉时间不够用。 50 | 51 | 所以也给明年找工作的录友们(2023届)提一个醒,现在就要系统性的准备起来了,因为明年春季实习招聘 是一个很好的进大厂的机会,剩下的时间也不是很多了。 52 | 53 | 来看看[知识星球](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ)里,一位准大三的录友准备的情况 54 | 55 | ![](https://code-thinking-1253855093.file.myqcloud.com/pics/星球大三.jpg) 56 | 57 | 再来看看一位准大二的录友准备情况 58 | 59 | ![](https://code-thinking-1253855093.file.myqcloud.com/pics/星球大二.jpg) 60 | 61 | **我已经预感到 这两位 等到秋招的时候就是稳稳的offer收割机**。 62 | 63 | [知识星球](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ)还有很多已经开始提前准备,或者看了 星球发文状态就开始着手准备的录友了。 64 | 65 | 66 | 所以 **所谓的大牛,都是 很早就规划自己要学的东西,很早就开始向过来人请教应该如何找工作,很早就知道自己应该学哪些技术,看哪些书, 这样等到找工作的时候,才是剑锋出鞘的时候**。 67 | 68 | 我们远远还没有到拼智商的程度。 69 | 70 | 这里 也是给公众号里的录友们提一个醒,估计还有不少录友依然在感觉时间还赶趟,但 未来的卷王已经在路上了 哈哈哈。 71 | 72 | **不过话说回来,现在互联网求职确实卷!** 73 | 74 | 但这是社会问题,我们改变不了。 75 | 76 | **卷的核心是,好的东西少,但要想的人多!** 77 | 78 | **如果你也想要,就要提前准备,提前规划,提前努力!** 79 | 80 | 也希望录友们都能找到一个自己心仪的工作,加油💪。 81 | 82 | -------------------------------------------------------------------------------- /problems/知识星球精选/不一样的七夕.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 | 6 | # 特殊的七夕 7 | 8 | 昨天在[知识星球](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ)发了一个状态: 9 | 10 | ![](https://code-thinking-1253855093.file.myqcloud.com/pics/20210815084126.png) 11 | 12 | 我还以为 过节嘛,录友们应该不会打卡了,但还依旧阻挡不辽录友打卡学习的步伐,来瞅瞅: 13 | 14 | 15 | ![](https://code-thinking-1253855093.file.myqcloud.com/pics/20210815100028.png) 16 | 17 | ![](https://code-thinking-1253855093.file.myqcloud.com/pics/20210815100109.png) 18 | 19 | ![](https://code-thinking-1253855093.file.myqcloud.com/pics/20210815100212.png) 20 | 21 | ![](https://code-thinking-1253855093.file.myqcloud.com/pics/20210815095902.png) 22 | 23 | 24 | 当然了,我截图了一小部分,星球里每天的信息量都非常大。 25 | 26 | 如果说一个人坚持每天总结记笔记,**其实是很容易放弃的,今天不记,明天不急,后天不整理感觉也无所谓**。 27 | 28 | 这样时间就一点一点的被浪费掉了。 29 | 30 | **因为我们学过的东西都会忘,不及时整理,时间就不能沉淀下来**,这就造成了一边学,一边忘,最后感觉自己好像也没学啥的感觉! 31 | 32 | 所以每天记笔记,及时整理,是非常重要的。 33 | 34 | 这个习惯其实靠自己约束很容易放弃,但一群人一起坚持,就会不一样,大家相互监督,每天不总结记录点什么就会感觉少了点啥。 35 | 36 | 而且,大家每天的总结,我都会看,有问题 我都及时指出来,这样也防止自己学着学着学跑偏了。 37 | 38 | 昨天我也在[知识星球](https://mp.weixin.qq.com/s/X1XCH-KevURi3LnakJsCkA)回答了几位录友的问题,其中有两个问题 还是比较典型的,估计公众号里的录友也会遇到这样的疑惑。 39 | 40 | 所以也给大家说一说: 41 | 42 | ## 准备的太晚了,想放弃秋招,直接准备春招 43 | 44 | ![](https://code-thinking-1253855093.file.myqcloud.com/pics/20210815091442.png) 45 | 46 | 很多准备今年秋招的录友感觉自己还没准备好,想先找实习,或者 自己在学习学习,然后直接春招。 47 | 48 | 其实不到万不得已,我还是建议要冲刺秋招。 49 | 50 | 如果说,因为没准备好,提前批放弃还是可以的,但秋招不能也直接放弃了! 51 | 52 | 秋招没找到好工作,一般11月份左右,一些大厂还会有补招,腾讯就经常补招,实在不行再准备春招,春招可能国企单位会多一些。 53 | 54 | **而且面试也很看缘分,永远没有真正准备好的时候,知识一直都学不完**,所以 把秋招当做最后的机会,就算秋招没找到,也可以在冲春招,而不是 直接放弃秋招。 55 | 56 | 还有就心态方面来说,直接放弃秋招,等 今年 10月份,身边同学都找到工作了,天天吃喝玩乐,见面打招呼就问:你去哪了,你签哪了。那时候 自己心里压力会非常大,甚至会影响 春招找工作。 57 | 58 | 59 | ## HR/面试官问你手上有没有其他offer,如何回答 60 | 61 | ![](https://code-thinking-1253855093.file.myqcloud.com/pics/20210815091819.png) 62 | 63 | 这个问题,无论是校招还是社招,大家都会遇到。 64 | 65 | 如果大家手上有其他更好的offer,或者说同等水平公司的offer,可以说一说,这样凸显出自己的优势,即:你们不要我,有更好的公司要我, 这样给面试官或者HR点压力,可以争取到更高的薪酬。 66 | 67 | 如果没有更好的offer,可以说没有,然后解释:只认准贵公司,从技术氛围,职业发展,公司前景,来说贵司多么多么的好,我多么渴望和贵司一起成长之类的。**总之,就是捧起来,显得自己很专一**。 68 | 69 | 都是套路,哈哈哈哈。 70 | 71 | **好了,说了这么多,希望对大家有所帮助**。 72 | 73 | 74 | -------------------------------------------------------------------------------- /problems/前序/广州互联网公司总结.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 | 6 |

7 |

欢迎大家参与本项目,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!

8 | 9 | 10 | # 广州互联网公司总结 11 | 12 | **个人总结难免有所疏忽,欢迎大家补充,公司好坏没有排名哈!** 13 | 14 | ## 一线互联网 15 | 16 | * 微信(总部) 有点难进! 17 | * 字节跳动(广州) 18 | 19 | ## 二线 20 | * 网易(总部)主要是游戏 21 | 22 | ## 三线 23 | 24 | * 唯品会(总部) 25 | * 欢聚时代(总部)旗下YY,虎牙,YY最近被浑水做空,不知百度还要不要收购了 26 | * 酷狗音乐(总部) 27 | * UC浏览器(总部)现在隶属阿里创始人何小鹏现在搞小鹏汽车 28 | * 荔枝FM(总部)用户可以在手机上开设自己的电台和录制节目 29 | * 映客直播(总部)股票已经跌成渣了 30 | * 爱范儿(总部) 31 | * 三七互娱(总部)游戏公司 32 | * 君海游戏(总部)游戏公司 33 | * 4399游戏(总部)游戏公司 34 | * 多益网络(总部)游戏公司 35 | 36 | ## 硬件巨头 (有软件/互联网业务) 37 | * 小鹏汽车(总部)新能源汽车小霸王 38 | 39 | ## 创业公司 40 | 41 | * 妈妈网(总部)母婴行业互联网公司 42 | * 云徙科技(总部)数字商业云服务提供商 43 | * Fordeal(总部)中东领先跨境电商平台 44 | * Mobvista(总部)移动数字营销 45 | * 久邦GOMO(总部)游戏 46 | * 深海游戏(总部)游戏 47 | 48 | ## 国企 49 | 50 | * 中国电信广州研发(听说没有996) 51 | 52 | 53 | ## 总结 54 | 55 | 同在广东省,难免不了要和深圳对比,大家如果看了这篇:[深圳原来有这么多互联网公司,你都知道么?](https://programmercarl.com/前序/深圳互联网公司总结.html)就能感受到鲜明的对比了。 56 | 57 | 广州大厂高端岗位其实比较少,本土只有微信和网易,微信呢毕竟还是腾讯的分部,而网易被很多人认为是杭州企业,其实网易总部在广州。 58 | 59 | 广州是唯一一个一线城市没有自己本土互联网巨头的城市,所以网易选择在广州扎根还是很正确的,毕竟杭州是阿里的天下,广州也应该扶持一把本土的互联网公司。 60 | 61 | 虽然对于互联网从业人员来说,广州的岗位要比深圳少很多,**但是!!广州的房价整体要比深圳低30%左右,而且广州的教育,医疗,公共资源完全碾压深圳**。 62 | 63 | 教育方面:大学广州有两个985,四个211,深圳这方面就不用说了,大家懂得。 64 | 65 | 基础教育方面深圳的小学初中高中学校数量远远不够用,小孩上学竞争很激烈,我也是经常听同事们说,耳濡目染了。 66 | 67 | 而医疗上基本深圳看不了的病都要往广州跑,深圳的医院数量也不够用。 68 | 69 | 在生活节奏上,广州更慢一些,更有生活的气息,而深圳生存下去的气息更浓烈一些。 70 | 71 | 所以很多在深圳打拼多年的IT从业者选择去广州安家也是有原因的。 72 | 73 | 但也有很多从广州跑到深圳的,深圳发展的机会更多,而广州教育医疗更丰富,房价不高(相对深圳)。 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | ----------------------- 83 |
84 | -------------------------------------------------------------------------------- /problems/知识星球精选/秋招总结2.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 | # 倒霉透顶,触底反弹! 6 | 7 | 星球里不少录友秋招已经陆续结束了,很多录友都在[知识星球](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ)里写下了自己的秋招总结,但今天这位录友很特殊,甚至我给她修改简历的时候我都“有点愁”。 8 | 9 | 他的秋招过程也是极其坎坷,**逼签、被养鱼最后收到感谢信、校招流程收到实习offer,还有数不清的简历挂……**,可能是太倒霉了,最后触底反弹,接到了百度的offer,虽然是白菜价,但真的很不错了。 10 | 11 | 这篇总结并没有说学习路线,而是说一说她自己的感想,算是另一个维度,感觉会对大家很有帮助,所以我也分享出来。 12 | 13 | ![](https://code-thinking-1253855093.file.myqcloud.com/pics/20211114111745.png) 14 | 15 | 以下星球原文: 16 | 17 | ------------- 18 | 19 | 秋招终于结束了,收到了百度C++开发、小米C++音视频开发、深信服C++开发、知乎go后端、神策java后端的offer,不是啥大佬,全是烂白菜,但是作为一个双非本的孩子,我觉得已经很幸运了,最终无脑选择了百度,春招还会再冲一波。 20 | 21 | **星球里的学习气氛很好,向卡尔哥问过好几个问题,每个都挺长,卡尔哥也给我耐心解答过,还帮我改过简历,感谢和大家相遇!** 关于学习路线大佬们说的很详细了,我觉得参考他们的已经足够有价值。**那我就为星球里还在奋斗的兄弟姐妹、以及学弟学妹们写一下我的一些其他的感想**。 22 | 23 | 1、**准备一定要趁早**。我是今年1月份准备的实习,那个时候我连C++智能指针都不知道,就一直陆续学着,6月份上岸滴滴实习,8月下旬跑路,可以说9月份才开始大规模投递。我是很菜的人,还不算勤奋,秋招不至于空手而归就是找实习的时候还有些积淀。 所以最大的感想就是,一定要越早越好,我认为理想的时间节点:3月份去实习,7月份投提前批,所以什么时候去准备可以根据这个时间去准备,当然越早越好。越早企业越缺人,越好进。 24 | 25 | 2、**多面试,哪怕实习不了也要多面试;多投简历,投了就有机会**。我没啥自主学习的意识,只有在要面试的前一个礼拜才会多少看点,还记得当时收到第二天就要腾讯面试的消息,前一天晚上我几乎通宵了,虽然最后还是挂了。但是我当时真的是要面试的恐惧支配着我学习 。 26 | 27 | 3、**八股文、看书和刷题**。实习面试的话看八股文还是能应付过去的,但是我看了大多数八股文感觉千篇一律,想真正化为自己的东西还是要看书,我一般喜欢看书,然后把书上的东西化为自己的理解记在笔记上。 刷题也是,我一般喜欢根据自己的理解把题归类,自己写题解。 28 | 29 | 4、**实习。我觉得实习比较好的时间节点是3月份(或者更早)**,暑假去实习如果不能保证转正,感觉还是有点耽误提前批,提前批是最最最好进大厂的一次。像我的话,白天工作一天到晚上九十点,回家就只想躺着,再遇上比较push的工作环境,做到实习和复习兼顾是有点难的。我觉得核心竞争力应该是基础知识的掌握程度,身边确实没有实习、但是基础和项目足够牛批的人也能进大厂,所以还需要做一个平衡吧。当然也不是劝退,实在平衡不了的话就要要根据自身情况吧。 30 | 31 | 但是实习确实让我简历好过了一些,这个就是实习最大的好处之一,但是我感觉像美团腾讯百度的话,如果笔试面试还可以的话,应该不太卡简历的。字节后端确实有点卡实习,还有一些没那么大但是也很强的厂是卡学历或者实习的。 32 | 33 | 5、还有秋招不要all in,不要all in ,不要all in!!! 34 | 35 | 以上就是我的一些感想,可能仁者见仁智者见智,希望大家多多指正。 36 | 37 | 我的秋招真的不是很顺利。逼签、被养鱼最后收到感谢信、校招流程收到实习offer,还有数不清的简历挂……,但是最后也有好的结果了,其实想的比较开,大不了就春招再进大厂呗。本来都要打算春招了,书都买了几本,但是没想到能收到百度意向,已经开始流程推进啦。 38 | 39 | 可能这就是倒霉透顶了就触底反弹吧。**一直觉得自己倒霉透了,奇葩的时间都被我遇上了,但是最后还是被好运眷顾了一下**。我的学校还是双非本,很一般的学校,所以任何时候都有机会,拿到offer不光是实力因素,运气成分也很大,大家一定要多投多面,万一哪次就上岸大厂了。 40 | 41 | **还是想参与一下春招,但是现在发现躺着太舒服啦**。还是得卷起来,争取以后能每天在星球里打卡哈哈 42 | 43 | 祝愿各位都有理想的offer!所愿皆所得! 44 | 45 | ------------- 46 | 47 | 以上就是星球里的原文,所以这位录友现在又可以愉快的在星球里,每日打卡了 哈哈哈。 48 | 49 | -------------------------------------------------------------------------------- /problems/前序/力扣上的代码想在本地编译运行?.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 | 6 |

7 |

欢迎大家参与本项目,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!

8 | 9 | 10 | 很多录友都问过我一个问题,就是力扣上的代码如何在本地编译运行? 11 | 12 | 其实在代码随想录刷题群里也经常出现这个场景,就是录友发一段代码上来,问大家这个代码怎么有问题? 如果我看到了一般我的回复:都是把那几个变量或者数组打印一下看看对不对,就知道了。 13 | 14 | 然后录友就问了:如何打日志呢? 15 | 16 | 其实在力扣上打日志也挺方便的,我一般调试就是直接在力扣上打日志,偶尔需要把代码粘到本地来运行添加日志debug一下。 17 | 18 | 在力扣上直接打日志,这个就不用讲,C++的话想打啥直接cout啥就可以了。 19 | 20 | 我来说一说力扣代码如何在本地运行。 21 | 22 | 毕竟我们天天用力扣刷题,也应该知道力扣上的代码如何在本地编译运行。 23 | 24 | 其实挺简单的,大家看一遍就会了。 25 | 26 | 我拿我们刚讲过的这道题[动态规划:使用最小花费爬楼梯](https://programmercarl.com/0746.使用最小花费爬楼梯.html)来做示范。 27 | 28 | 力扣746. 使用最小花费爬楼梯,完整的可以在直接本地运行的C++代码如下: 29 | 30 | ```CPP 31 | #include 32 | #include 33 | using namespace std; 34 | 35 | class Solution { 36 | public: 37 | int minCostClimbingStairs(vector& cost) { 38 | vector dp(cost.size()); 39 | dp[0] = cost[0]; 40 | dp[1] = cost[1]; 41 | for (int i = 2; i < cost.size(); i++) { 42 | dp[i] = min(dp[i - 1], dp[i - 2]) + cost[i]; 43 | } 44 | return min(dp[cost.size() - 1], dp[cost.size() - 2]); 45 | } 46 | }; 47 | 48 | int main() { 49 | int a[] = {1, 100, 1, 1, 1, 100, 1, 1, 100, 1}; 50 | vector cost(a, a + sizeof(a) / sizeof(int)); 51 | Solution solution; 52 | cout << solution.minCostClimbingStairs(cost) << endl; 53 | } 54 | ``` 55 | 56 | 大家可以拿去跑一跑,直接粘到编译器上就行了。 57 | 58 | 我用的是linux下gcc来编译的,估计粘到其他编译器也没问题。 59 | 60 | 代码中可以看出,其实就是定义个main函数,构造个输入用例,然后定义一个solution变量,调用minCostClimbingStairs函数就可以了。 61 | 62 | 此时大家就可以随意构造测试数据,然后想怎么打日志就怎么打日志,没有找不出的bug,哈哈。 63 | 64 | 65 | 66 | 67 | 68 | 69 | ----------------------- 70 |
71 | -------------------------------------------------------------------------------- /problems/知识星球精选/客三消.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 | 6 | # 客三消! 7 | 8 | 给大家科普一下:什么是客三消。 9 | 10 | 翻译过来就是客户端三年消失。 11 | 12 | **听起来是不是有点吓人**!这种说法略夸张,但只要能传开,就说明客户端一定有一些困局,并不是空穴来风。 13 | 14 | 昨天卡哥在朋友圈里分享了一个段子的截图 15 | 16 | ![](https://code-thinking-1253855093.file.myqcloud.com/pics/IMG_3986.jpg) 17 | 18 | 然后朋友圈就炸了,上百条的留言,问我这是为啥。 19 | 20 | 其实这个问题在[知识星球](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ)里也有录友问过我。 21 | 22 | ![](https://code-thinking-1253855093.file.myqcloud.com/pics/20210905091037.png) 23 | 24 | 当时已经详细的回答了一波,估计很多录友都有这方面的困惑,所以在公众号上再来给大家讲一讲。 25 | 26 | **关于星球提问中SRE和后端,在这里就不介绍了,卡哥重点说一说,客户端**。 27 | 28 | 客户端目前比较突出的问题,主要是 这四点: 29 | 30 | 1. 客户端岗位需求相对较小,而且有越来越小的趋势 31 | 32 | 2. 技术做深相对较难 33 | 34 | 3. 客户端晋升相对困难 35 | 36 | 4. 中年危机 (其实程序员有,不过客户端可能更明显一些) 37 | 38 | 39 | ## 岗位需求相对较小 40 | 41 | 客户端需求的减少,主要是体现在中小厂,或者说创业公司,因为大家都养不起原生客户端,基本都会采用跨端的技术方案,也就是大前端(即一套代码可以编译出各个端的版本,包括安卓,IOS等各种终端)。 42 | 43 | 这样就节省了很大的人力,不过目前在功能上一定没有 原生客户端体验好。 44 | 45 | **但大前端取代客户端是技术趋势!** 46 | 47 | 如果选择客户端,那么就多少要掌握一些跨端技术方案。 48 | 49 | 互联网软件的思维,就是轻前端,重后端,为什么PC软件搬到了浏览器上,移动APP搬到小程序上,都是这个道理,一般重头戏在后端。 50 | 51 | 所以后端的需求才会比较大。 52 | 53 | ## 技术做深相对较难 54 | 55 | 这里就不止客户端,其实前端都有这个问题。 56 | 57 | 关于前端和客户端的区别,其实没有那么严格的定义,大家可以理解 前端包含了客户端。一切可视化皆为前端。 58 | 59 | 前端框架、渲染引擎 变化相对快,可能你刚熟悉一个框架,然后就换了,最关键是可能还拿不准哪一种框架日后会成为主流,一不小心就跑偏了。 60 | 61 | 而后端框架变化相对就慢得多,而且 更容易(或者说更有机会)把技术做深,因为 高并发,高可用,低延迟 这些基本都是后端的工作。 62 | 63 | 正是前端 技术栈更新太快,所以要持续高强度学习 (这种学习可能不是往深去学习,而是 适应一个又一个框架的学习)。 64 | 65 | 而且前端 很容易陷入需求的反复变化之中,因为一个功能或者界面的修改,都是前端同学的工作量。 66 | 67 | 后端可能 什么都不用改,接口都是一样的,然后就可以空出时间研究技术。 68 | 69 | ## 晋升 70 | 71 | 目前在大厂,客户端职业天花板相对较低,一般情况下,可能到组长就到头了。 72 | 73 | 搞技术一路升上去,甚至到CTO的,基本都是后端,这也是因为前面讲过的:大部分的互联网产品,重头戏在后端,所有后端更有机会把技术做深,更直白说,后端更有机会在晋升做ppt的时候 “吹牛逼”。 74 | 75 | 76 | ## 中年危机 77 | 78 | 这个就更范范一些了,程序员都有这个危机,不过客户端可能更突出一些。 79 | 80 | 原生客户端的岗位需求确实会越来越少,如果继续干下去,没有晋升到管理层,然后退居二线公司,发现二线公司都没有原生客户端的岗位,那么就非常被动了。 81 | 82 | 所以可以往大前端的方向去转。 83 | 84 | 大前端现在也有很多技术方案,ReactNative和weex(阿里,脸书的方案),Flutter(Google的方案),微信小程序(腾讯的方案) 85 | 86 | 不过最终哪一个方案一统天下,这还是未知数,所以就需要持续学习咯。 87 | 88 | # 总结 89 | 90 | 以上就是我在[知识星球](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ)里的详细回答。 91 | 92 | 注意我这里说的一般情况,当然各个岗位都有佼佼者,或者说大牛,客户端也有大牛,也很香,不过这是极少数,就不在讨论范围内了。 93 | 94 | 希望对大家理解目前客户端的趋势有所帮助。 95 | 96 | -------------------------------------------------------------------------------- /problems/知识星球精选/HR面注意事项.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 | 6 | 7 | # HR面注意事项 8 | 9 | [知识星球](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ)里已经有一些录友开始准备HR面。 10 | 11 | ![](https://code-thinking-1253855093.file.myqcloud.com/pics/20210807155107.png) 12 | 13 | 甚至星球里已经有录友拿到百度提前批的offer 14 | 15 | ![](https://code-thinking-1253855093.file.myqcloud.com/pics/20210808102821.png) 16 | 17 | 看到一些录友面试这么顺利还是非常开心的,同时我也在知识星球里分享了HR面最容易遇到的 问题,已经应该如何回答。 18 | 19 | 相信公众号里不少录友也会遇到同样的问题,所以就给大家再分享一下。 20 | 21 | HR面的话,如果不犯重大问题,一般不会刷人。 22 | 23 | 但有些同学也会犯重大问题,这样丢了offer,可就太可惜了。 24 | 25 | **HR的职责是选择符合公司文化价值观的员工**,那么说到文化价值观,大家可能感觉 这虚无缥缈的,怎么能证明自己符合文化价值观呢。 26 | 27 | 其实HR主要从如下几个问题来考察,大家只要把这几个问题想清楚,就差不多了。 28 | 29 | 30 | ## 为什么选择我们公司? 31 | 32 | 这个大家一定要有所准备,不能被问到了之后一脸茫然,然后说 “就是想找个工作”,那基本就没戏了 33 | 34 | 要从**技术氛围,职业发展,公司潜力**等等方面来说自己为什么选择这家公司。 35 | 36 | 要表现自己如何如何看好这家公司,期待和这家公司一起成长。 37 | 38 | ## 有没有职业规划? 39 | 40 | 一般应届生都没有明确的职业规划,不过当HR问起来的时候,不要说 自己想工作几年想做项目经理,工作几年想做产品经理,甚至想当leader带团队,这样会被HR认为 职业规划不清晰,尽量从技术的角度规划自己。 41 | 42 | 这个策略同样适用于社招。 43 | 44 | 虽然大部分程序员的终极目标都想做leader,或者做管理,(极少数想要写一辈子代码的大牛除外,不过国内环境对这种大牛并不友好) 45 | 46 | 大家都想做战略做规划,那比写代码有意思,有成就感多了。 47 | 48 | 但不要说出来,一定要围绕技术这块来规划,根据你的岗位,**一年 技术达到什么程度,三年在某个技术领域有深入研究,五年成为技术专家之类的**等等。 49 | 50 | 这块其实我和HR朋友还真的讨论过,我说:就大厂,百分之九十五以上的程序员都不想写代码,以后指定是想转产品或者升leader做项目管理, 但你为什么还要问这么 无聊的问题呢。 51 | 52 | HR朋友的回答是:你不说真相,我会认为你可能对技术有追求,但如果你说出真相,那么明确你对技术没有追求。 53 | 54 | 所以,即使你有其他想法,在职业规划HR面的时候,**也要仅仅围绕技术,树立自己要深耕技术的形象**。 55 | 56 | ## 是否接受加班? 57 | 58 | 虽然大家都不喜欢加班,但是这个问题,我还是建议如果手头没有offer的话,大家尽量选择接受了吧 59 | 60 | 就说:自己可以介绍 XX程度的加班。 61 | 62 | 如果确实身体不适,那就直接拒绝,毕竟健康是第一位。 63 | 64 | ## 坚持最长的一件事情是什么? 65 | 66 | 这个问题,大家最好之前就想好,有一些同学可能印象里自己没有坚持很长的事情,也没有好好想过这个问题,在HR面的时候被问到的时候,一脸茫然,不知道该说啥。 67 | 68 | 憋了半天说出一个不痛不痒的事情。这就是一个减分项了! 69 | 70 | 问这个问题主要是考察大家的韧性,会不会做一个件事遇到困难就中途放弃了。 71 | 72 | 星球里的录友可以说自己坚持每日打卡总结,这也是可以的,毕竟这种需要自己克制才能做到的事情。 73 | 74 | ## 如果校招,直接会问:期望薪资XXX是否接受? 75 | 76 | 这里大家如果感觉自己表现的很好 给面试官留下的很好的印象,**可以在这里争取 special offer** 77 | 78 | 这都是可以的,但是要真的对自己信心十足。 79 | 80 | ## 如果社招,则会了解前一家目前公司薪水多少 ? 81 | 82 | **这里大家切记不要虚报工资,因为入职前是要查流水的,也就是要把上一件公司的银行流水截图报上来,这个是比较严肃的问题。** 83 | 84 | 85 | 好了,说了这么多,希望对大家有所帮助。 86 | 87 | --------------- 88 | 89 | 加入「代码随想录」知识星球,[点击这里](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ) 90 | -------------------------------------------------------------------------------- /problems/贪心算法理论基础.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 |

参与本项目,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!

6 | 7 | 8 | # 关于贪心算法,你该了解这些! 9 | 10 | 题目分类大纲如下: 11 | 12 | 贪心算法大纲 13 | 14 | 15 | ## 什么是贪心 16 | 17 | **贪心的本质是选择每一阶段的局部最优,从而达到全局最优**。 18 | 19 | 这么说有点抽象,来举一个例子: 20 | 21 | 例如,有一堆钞票,你可以拿走十张,如果想达到最大的金额,你要怎么拿? 22 | 23 | 指定每次拿最大的,最终结果就是拿走最大数额的钱。 24 | 25 | 每次拿最大的就是局部最优,最后拿走最大数额的钱就是推出全局最优。 26 | 27 | 再举一个例子如果是 有一堆盒子,你有一个背包体积为n,如何把背包尽可能装满,如果还每次选最大的盒子,就不行了。这时候就需要动态规划。动态规划的问题在下一个系列会详细讲解。 28 | 29 | ## 贪心的套路(什么时候用贪心) 30 | 31 | 很多同学做贪心的题目的时候,想不出来是贪心,想知道有没有什么套路可以一看就看出来是贪心。 32 | 33 | **说实话贪心算法并没有固定的套路**。 34 | 35 | 所以唯一的难点就是如何通过局部最优,推出整体最优。 36 | 37 | 那么如何能看出局部最优是否能推出整体最优呢?有没有什么固定策略或者套路呢? 38 | 39 | **不好意思,也没有!** 靠自己手动模拟,如果模拟可行,就可以试一试贪心策略,如果不可行,可能需要动态规划。 40 | 41 | 有同学问了如何验证可不可以用贪心算法呢? 42 | 43 | **最好用的策略就是举反例,如果想不到反例,那么就试一试贪心吧**。 44 | 45 | 可有有同学认为手动模拟,举例子得出的结论不靠谱,想要严格的数学证明。 46 | 47 | 一般数学证明有如下两种方法: 48 | 49 | * 数学归纳法 50 | * 反证法 51 | 52 | 看教课书上讲解贪心可以是一堆公式,估计大家连看都不想看,所以数学证明就不在我要讲解的范围内了,大家感兴趣可以自行查找资料。 53 | 54 | **面试中基本不会让面试者现场证明贪心的合理性,代码写出来跑过测试用例即可,或者自己能自圆其说理由就行了**。 55 | 56 | 举一个不太恰当的例子:我要用一下1+1 = 2,但我要先证明1+1 为什么等于2。严谨是严谨了,但没必要。 57 | 58 | 虽然这个例子很极端,但可以表达这么个意思:**刷题或者面试的时候,手动模拟一下感觉可以局部最优推出整体最优,而且想不到反例,那么就试一试贪心**。 59 | 60 | **例如刚刚举的拿钞票的例子,就是模拟一下每次拿做大的,最后就能拿到最多的钱,这还要数学证明的话,其实就不在算法面试的范围内了,可以看看专业的数学书籍!** 61 | 62 | 所以这也是为什么很多同学通过(accept)了贪心的题目,但都不知道自己用了贪心算法,**因为贪心有时候就是常识性的推导,所以会认为本应该就这么做!** 63 | 64 | **那么刷题的时候什么时候真的需要数学推导呢?** 65 | 66 | 例如这道题目:[链表:环找到了,那入口呢?](https://programmercarl.com/0142.环形链表II.html),这道题不用数学推导一下,就找不出环的起始位置,想试一下就不知道怎么试,这种题目确实需要数学简单推导一下。 67 | 68 | ## 贪心一般解题步骤 69 | 70 | 贪心算法一般分为如下四步: 71 | 72 | * 将问题分解为若干个子问题 73 | * 找出适合的贪心策略 74 | * 求解每一个子问题的最优解 75 | * 将局部最优解堆叠成全局最优解 76 | 77 | 其实这个分的有点细了,真正做题的时候很难分出这么详细的解题步骤,可能就是因为贪心的题目往往还和其他方面的知识混在一起。 78 | 79 | ## 总结 80 | 81 | 本篇给出了什么是贪心以及大家关心的贪心算法固定套路。 82 | 83 | **不好意思了,贪心没有套路,说白了就是常识性推导加上举反例**。 84 | 85 | 最后给出贪心的一般解题步骤,大家可以发现这个解题步骤也是比较抽象的,不像是二叉树,回溯算法,给出了那么具体的解题套路和模板。 86 | 87 | 本篇没有配图,其实可以找一些动漫周边或者搞笑的图配一配(符合大多数公众号文章的作风),但这不是我的风格,所以本篇文字描述足以! 88 | 89 | 90 | 91 | ----------------------- 92 |
93 | -------------------------------------------------------------------------------- /problems/知识星球精选/关于实习大家的疑问.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 | 6 | # 关于实习,大家可能有点迷茫! 7 | 8 | 我在[知识星球](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ)里回答了很多关于实习相关的问题,其实很多录友可能都有这么样的疑问,主要关于实习的问题有如下四点: 9 | 10 | * 秋招什么时候开始准备 11 | * 要不要准备实习 12 | * 实习是不是重要? 13 | * 什么时候找实习最有帮助 14 | * 如何选择实习的offer 15 | 16 | 下面都分别来说一说: 17 | 18 | ## 秋招什么时候开始准备 19 | 20 | ![实习二](https://img-blog.csdnimg.cn/20210502145513517.png) 21 | 22 | **准备工作指定是越早越好的**。 23 | 24 | 准备的越早,在8,9月份就越淡定,每年校招很多同学都会对于准备找工作总感觉赶趟赶趟,结果到了8月份开始慌得一笔了。 25 | 26 | 正常校招8月份就开始提前批(各大企业提前抢优秀毕业生)了,有的企业甚至7月份就开始。 27 | 28 | 基本到了7月份可能就没有整块的时间静下心来准备找工作,那时候已经铺天盖地的各种招聘信息,甚至一些同学已经拿到了offer了。 29 | 30 | 所以准备找工作的内容以7月为终结点比较稳妥,七月份之后以复习为主,有个整体框架,定时复习补充补充,多和同学交流面试经验。 31 | 32 | ## 要不要准备实习 33 | 34 | 有的同学是3,4月份准备面实习,然后7、8月份就去企业实习了,**实习有利有弊**。 35 | 36 | 如果可以去一线互联网公司实习,而且岗位也合适,那当然要去,如果去不了也别难过,因为实习生大部分都是打杂,干的活甚至都写不到简历上。 37 | 38 | 也有一小部分的实习生能够真正做到项目。 39 | 40 | 如果没有去实习,就把基础好好补充一下,**基础打好,毕竟对于应届生基础最为重要**, 编程语言、数据结构算法、计算机网络、操作系统、数据库这些都是基础,规划好时间把这些内容学好。 41 | 42 | **对于应届生来说,项目经历是锦上添花,不是决定性的**。 43 | 44 | 有实习经历(前提是实习工作内容是真正的做项目,不是打杂),那么面试的时候面试官可能对项目经历感兴趣,问基础的内容就比较少, 如果没有实习经历,就把基础内容巩固一下,校招是一样的。 45 | 46 | ## 实习是不是非常重要? 47 | 48 | ![实习一](https://img-blog.csdnimg.cn/20210502114600147.png) 49 | 50 | **大厂的实习经历对秋招还是很有帮助的**。 51 | 52 | 53 | 但也不绝对,实习的话会耽误三个月左右,如果没有转正,而且一直在打杂的话,再去找秋招工作,**那时候一些基础的内容就都忘光了,反而秋招很被动**。 54 | 55 | 现在当然也可以按照准备找实习的状态来要求自己,给自己点压力,毕竟找实习准备的知识和秋招准备的知识差不多。 56 | 57 | 也可以提前经历一下面试,培养一下面试感觉,数据库方面知识你比较短缺,可以通过大量看这方面的面经迅速补充一下(秋招之前还可以系统看一看)。 58 | 59 | 如果拿到了大厂的实习offer,就去吧,实习的时候心里要有个秤,如果工作是打杂,就要尽快自己抽时间看基础准备秋招。 60 | 61 | **另外需要注意的是,有些公司投递过简历面试没通过是有记录的,所以投递要当心,不要感觉投简历没有成本**,我知道的例如阿里,你每次投简历都有记录,如果实习面试都挂了,秋招的时候面试官也会看当时实习面试的记录(会考虑当时实习面试的结果)。 62 | 63 | ## 什么时候找实习最有帮助 64 | 65 | ![在这里插入图片描述](https://img-blog.csdnimg.cn/20210502151249354.png) 66 | 67 | 6月份那时候基本不招实习生了,找的话也是日常实习(没有转正,实习时间是比较长的,要六个月),如果不是暑期实习就直接准备秋招吧。 68 | 69 | **只有应届的暑期实习才有转正的机会,因为企业这样安排也是为了提前发现优秀毕业生!** 70 | 71 | 例如:今年暑期实习,只招明年毕业的应届生。 72 | 73 | 74 | ## 如何选择实习的offer 75 | 76 | ![在这里插入图片描述](https://img-blog.csdnimg.cn/20210502152023574.png) 77 | 78 | 如果目标应该是C++后端开发,那客户端实习offer可以选择别去了。 或者 选一个实习时间最短的offer先去着,例如两个月之类的,这样既能体现一下工作流程,也别耽误太多时间(毕竟客户端开发不是你的目标)。 79 | 80 | **实习也不是必要的,一要看实习的岗位,是不是你想要的工作,二是实习的内容是不是打杂**,一些实习岗位其实是在浪费时间,如果转正不了的话,秋招就特别被动了,耽误了复习基础的时间。 81 | 82 | 还有就是**秋招的时候,一定要找小公司先练手,然后在面大公司**。 83 | 84 | 85 | 以上基本覆盖了大家对实习的各种疑惑,不过现在已经到了5月份,实习面试基本结束了,如果没有拿到实习offer,大家安心准备秋招吧,依然可以冲刺大厂! 86 | 87 | 88 | -------------------------------------------------------------------------------- /problems/前序/关于空间复杂度,可能有几个疑问?.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 | 6 |

7 |

欢迎大家参与本项目,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!

8 | 9 | 10 | 11 | # 空间复杂度分析 12 | 13 | * [关于时间复杂度,你不知道的都在这里!](https://programmercarl.com/前序/关于时间复杂度,你不知道的都在这里!.html) 14 | * [$O(n)$的算法居然超时了,此时的n究竟是多大?](https://programmercarl.com/前序/On的算法居然超时了,此时的n究竟是多大?.html) 15 | * [通过一道面试题目,讲一讲递归算法的时间复杂度!](https://programmercarl.com/前序/通过一道面试题目,讲一讲递归算法的时间复杂度!.html) 16 | 17 | 那么一直还没有讲空间复杂度,所以打算陆续来补上,内容不难,大家可以读一遍文章就有整体的了解了。 18 | 19 | 什么是空间复杂度呢? 20 | 21 | 是对一个算法在运行过程中占用内存空间大小的量度,记做$S(n)=O(f(n)$。 22 | 23 | 空间复杂度(Space Complexity)记作S(n) 依然使用大O来表示。利用程序的空间复杂度,可以对程序运行中需要多少内存有个预先估计。 24 | 25 | 关注空间复杂度有两个常见的相关问题 26 | 27 | 1. 空间复杂度是考虑程序(可执行文件)的大小么? 28 | 29 | 很多同学都会混淆程序运行时内存大小和程序本身的大小。这里强调一下**空间复杂度是考虑程序运行时占用内存的大小,而不是可执行文件的大小。** 30 | 31 | 2. 空间复杂度是准确算出程序运行时所占用的内存么? 32 | 33 | 不要以为空间复杂度就已经精准的掌握了程序的内存使用大小,很多因素会影响程序真正内存使用大小,例如编译器的内存对齐,编程语言容器的底层实现等等这些都会影响到程序内存的开销。 34 | 35 | 所以空间复杂度是预先大体评估程序内存使用的大小。 36 | 37 | 说到空间复杂度,我想同学们在OJ(online judge)上应该遇到过这种错误,就是超出内存限制,一般OJ对程序运行时的所消耗的内存都有一个限制。 38 | 39 | 为了避免内存超出限制,这也需要我们对算法占用多大的内存有一个大体的预估。 40 | 41 | 同样在工程实践中,计算机的内存空间也不是无限的,需要工程师对软件运行时所使用的内存有一个大体评估,这都需要用到算法空间复杂度的分析。 42 | 43 | 来看一下例子,什么时候的空间复杂度是$O(1)$呢,C++代码如下: 44 | 45 | ```CPP 46 | int j = 0; 47 | for (int i = 0; i < n; i++) { 48 | j++; 49 | } 50 | 51 | ``` 52 | 第一段代码可以看出,随着n的变化,所需开辟的内存空间并不会随着n的变化而变化。即此算法空间复杂度为一个常量,所以表示为大$O(1)$。 53 | 54 | 什么时候的空间复杂度是$O(n)$? 55 | 56 | 当消耗空间和输入参数n保持线性增长,这样的空间复杂度为$O(n)$,来看一下这段C++代码 57 | ```CPP 58 | int* a = new int(n); 59 | for (int i = 0; i < n; i++) { 60 | a[i] = i; 61 | } 62 | ``` 63 | 64 | 我们定义了一个数组出来,这个数组占用的大小为n,虽然有一个for循环,但没有再分配新的空间,因此,这段代码的空间复杂度主要看第一行即可,随着n的增大,开辟的内存大小呈线性增长,即 $O(n)$。 65 | 66 | 其他的 $O(n^2)$, $O(n^3)$ 我想大家应该都可以以此例举出来了,**那么思考一下 什么时候空间复杂度是 $O(\log n)$呢?** 67 | 68 | 空间复杂度是logn的情况确实有些特殊,其实是在**递归的时候,会出现空间复杂度为logn的情况**。 69 | 70 | 至于如何求递归的空间复杂度,我会在专门写一篇文章来介绍的,敬请期待! 71 | 72 | 73 | 74 | 75 | ----------------------- 76 |
77 | -------------------------------------------------------------------------------- /problems/知识星球精选/写简历的一些问题.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 | 6 | # 程序员应该这么写简历! 7 | 8 | 自运营[知识星球](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ)以来,我已经给星球里的录友们看了 一百多份简历,并准对大家简历上的问题都给出了对应的详细建议。 9 | 10 | 社招,校招,实习的都有,其实大家的简历看多了,发现有很多共性的问题,这里就和大家分享一下。 11 | 12 | 我的简历模板也分享出来了,大家在「代码随想录」后台回复:简历模板,就可以获取! 13 | 14 | # 简历布局 15 | 16 | 不少录友的简历布局就很不合理, 有的把专业技能放在最下面了,有的甚至把教育经历放下面了,建议简历布局的顺序是这样: 17 | 18 | * 教育工作经历 19 | * 专业技能 20 | * 项目经验 21 | * 荣誉奖项 22 | * 个人简述 23 | 24 | # 教育工作经历 25 | 26 | 一些录友可能本科学历不是很好,然后 简历上直接不写自己的本科学校。 27 | 28 | 其实教育经历是最基本的,你不写 面试官也一定会问,问出来 那么感觉更不好,所以关于教育经历,大家是一定要写的。 29 | 30 | 写本科以后教育经历的就行了,一些录友可能是 高中就读了一些特别牛逼的高中,然后把高中也写出来了,哈哈哈,高中经历真的就不用写了。 31 | 32 | 还有一些社招的录友,研究生和本科之间空了几年,这几年 一定要说清楚做了些什么,甚至是“编一下”,因为这个面试官也会问的。 33 | 34 | # 专业技能 35 | 36 | 一些录友简历上没有「专业技能」这一栏,或者写的很短。 37 | 38 | 可能是不知道该写啥,甚至就不写了。 39 | 40 | 通常「专业技能」是在 「教育工作经历」之后的,我这里给出一个模板,大家按照这个格式来写「专业技能」就可以。 41 | 42 | 1. 熟练使用 C++,掌握Go,了解 Java、Python、PHP 等编程语言 43 | 2. 熟练使用 linux 下 vim、Git 开发环境 44 | 3. 了解 Linux 下网络编程、TCP/IP 协议 45 | 4. 掌握基础数据结构和算法的基本原理 46 | 5. 英语六级:XXX 47 | 48 | 49 | 一些录友会列举自己主修的课程,列了一堆,其实凑篇幅 我是理解的,就是感觉简历太单薄的,列课程来凑。 50 | 51 | 但大家凑篇幅 尽力在「专业技能」和「项目经验」上凑篇幅,如果把 自己主修可能都列出来,会让面试官感觉没有什么干货。(有的同学甚至靠留白才凑篇幅,这就更不要了) 52 | 53 | 当然应届生如果有一些课程自己成绩确实很好,可以和「教育经历」写在一起,简单并行列举一下就可以了。 54 | 55 | # 项目经验 56 | 57 | 很多录友写项目经验就是流水账,这是什么项目,自己完成了功能1,2,3,4。堆了很多字。 58 | 59 | 要知道面试官是不了解你的项目的,面试也只有 一个小时左右的时间,如果堆了很多文字 面试官也懒得去读。 60 | 61 | 面试官最在意的是什么呢? 62 | 63 | **项目中有哪些技术难点,以及 你是如何克服的**。 64 | 65 | 这是面试官最关心的,也是最能体现出候选人技术深度的问题。 66 | 67 | 所以大家在描述项目经验的时候,一定要时刻想着,这个项目的难点究竟是什么,要反复问自己这个问题。 68 | 69 | 可能有的同学说了,我这项目本来就没有难点啊,就是1,2,3,4功能,然后 遇到不会的,百度搜一下,差不多就这样了。 70 | 71 | **项目没有难点,也要自己“造难点”**。 因为这个问题是面试官必问的! 72 | 73 | 所以一定要准备好。 74 | 75 | 还有不少录友的项目经历都写了 web server,使用线程池 + 非阻塞 socket + epoll(ET 和 LT) + 事件处理 (Reactor 和模拟 Proactor) 等等。 76 | 77 | 这个项目可能是很多准备后台开发的同学 首选的 项目。 78 | 79 | 这种自己搞的小项目,**最好把你的代码上传的github上,然后在简历中贴出github地址**,面试官一定会看的。 80 | 81 | 如果看你的代码写的确实不错,那指定是加分项。比简历上写的天花乱坠都强! 82 | 83 | 还有的同学项目经历特别多,写了5,6个项目,每个项目都是概述了一下自己做了XXX。 84 | 85 | 其实面试官,基本就会和你深入聊 2个的项目左右,列举这么多项目没有用的,关键这些项目一看也是技术含量不大。 86 | 87 | **所以不用单纯堆项目个数。项目经历 两个足够,把两个项目搞深搞透** 88 | 89 | 90 | # 校园经历 91 | 92 | 一些录友会把自己学校工作列出一大堆,例如各种学生会啊,创新部门啊之类的。甚至有的会把自己的减肥经历也列举出来。 93 | 94 | 如果面技术岗位,这一块其实不是面试官关心的,可以在 最后一栏「个人简述」,简单一两句概括一下自己的学生会经历就好,表明自己沟通能力没问题。 95 | 96 | 关于标明自己有毅力,有恒心,不怕吃苦等等,都简单一句概括。 97 | 98 | 99 | 好了,关于简历的问题,我就先分享这些,估计应该击中了不少录友的痛点了。 100 | 101 | -------------------------------------------------------------------------------- /problems/周总结/20201203贪心周末总结.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 本周小结!(贪心算法系列二) 4 | 5 | ## 周一 6 | 7 | 一说到股票问题,一般都会想到动态规划,其实有时候贪心更有效! 8 | 9 | 在[贪心算法:买卖股票的最佳时机II](https://programmercarl.com/0122.买卖股票的最佳时机II.html)中,讲到只能多次买卖一支股票,如何获取最大利润。 10 | 11 | **这道题目理解利润拆分是关键点!** 不要整块的去看,而是把整体利润拆为每天的利润,就很容易想到贪心了。 12 | 13 | **局部最优:只收集每天的正利润,全局最优:得到最大利润**。 14 | 15 | 如果正利润连续上了,相当于连续持有股票,而本题并不需要计算具体的区间。 16 | 17 | 如图: 18 | 19 | ![122.买卖股票的最佳时机II](https://img-blog.csdnimg.cn/2020112917480858.png) 20 | 21 | ## 周二 22 | 23 | 在[贪心算法:跳跃游戏](https://programmercarl.com/0055.跳跃游戏.html)中是给你一个数组看能否跳到终点。 24 | 25 | 本题贪心的关键是:**不用拘泥于每次究竟跳几步,而是看覆盖范围,覆盖范围内一定是可以跳过来的,不用管是怎么跳的**。 26 | 27 | **那么这个问题就转化为跳跃覆盖范围究竟可不可以覆盖到终点!** 28 | 29 | 贪心算法局部最优解:移动下标每次取最大跳跃步数(取最大覆盖范围),整体最优解:最后得到整体最大覆盖范围,看是否能到终点 30 | 31 | 如果覆盖范围覆盖到了终点,就表示一定可以跳过去。 32 | 33 | 如图: 34 | 35 | ![55.跳跃游戏](https://img-blog.csdnimg.cn/20201124154758229.png) 36 | 37 | 38 | ## 周三 39 | 40 | 这道题目:[贪心算法:跳跃游戏II](https://programmercarl.com/0045.跳跃游戏II.html)可就有点难了。 41 | 42 | 本题解题关键在于:**以最小的步数增加最大的覆盖范围,直到覆盖范围覆盖了终点**。 43 | 44 | 那么局部最优:求当前这步的最大覆盖,那么尽可能多走,到达覆盖范围的终点,只需要一步。整体最优:达到终点,步数最少。 45 | 46 | 如图: 47 | 48 | ![45.跳跃游戏II](https://img-blog.csdnimg.cn/20201201232309103.png) 49 | 50 | 注意:**图中的移动下标是到当前这步覆盖的最远距离(下标2的位置),此时没有到终点,只能增加第二步来扩大覆盖范围**。 51 | 52 | 在[贪心算法:跳跃游戏II](https://programmercarl.com/0045.跳跃游戏II.html)中我给出了两个版本的代码。 53 | 54 | 其实本质都是超过当前覆盖范围,步数就加一,但版本一需要考虑当前覆盖最远距离下标是不是数组终点的情况。 55 | 56 | 而版本二就比较统一的,超过范围,步数就加一,但在移动下标的范围了做了文章。 57 | 58 | 即如果覆盖最远距离下标是倒数第二点:直接加一就行,默认一定可以到终点。如图: 59 | ![45.跳跃游戏II2](https://img-blog.csdnimg.cn/20201201232445286.png) 60 | 61 | 如果覆盖最远距离下标不是倒数第二点,说明本次覆盖已经到终点了。如图: 62 | ![45.跳跃游戏II1](https://img-blog.csdnimg.cn/20201201232338693.png) 63 | 64 | 有的录友认为版本一好理解,有的录友认为版本二好理解,其实掌握一种就可以了,也不用非要比拼一下代码的简洁性,简洁程度都差不多了。 65 | 66 | 我个人倾向于版本一的写法,思路清晰一点,版本二会有点绕。 67 | 68 | ## 周四 69 | 70 | 这道题目:[贪心算法:K次取反后最大化的数组和](https://programmercarl.com/1005.K次取反后最大化的数组和.html)就比较简单了,哈哈,用简单题来讲一讲贪心的思想。 71 | 72 | **这里其实用了两次贪心!** 73 | 74 | 第一次贪心:局部最优:让绝对值大的负数变为正数,当前数值达到最大,整体最优:整个数组和达到最大。 75 | 76 | 处理之后,如果K依然大于0,此时的问题是一个有序正整数序列,如何转变K次正负,让 数组和 达到最大。 77 | 78 | 第二次贪心:局部最优:只找数值最小的正整数进行反转,当前数值可以达到最大(例如正整数数组{5, 3, 1},反转1 得到-1 比 反转5得到的-5 大多了),全局最优:整个 数组和 达到最大。 79 | 80 | [贪心算法:K次取反后最大化的数组和](https://programmercarl.com/1005.K次取反后最大化的数组和.html)中的代码,最后while处理K的时候,其实直接判断奇偶数就可以了,文中给出的方式太粗暴了,哈哈,Carl大意了。 81 | 82 | 例外一位录友留言给出一个很好的建议,因为文中是使用快排,仔细看题,**题目中限定了数据范围是正负一百,所以可以使用桶排序**,这样时间复杂度就可以优化为$O(n)$了。但可能代码要复杂一些了。 83 | 84 | 85 | ## 总结 86 | 87 | 大家会发现本周的代码其实都简单,但思路却很巧妙,并不容易写出来。 88 | 89 | 如果是第一次接触的话,其实很难想出来,就是接触过之后就会了,所以大家不用感觉自己想不出来而烦躁,哈哈。 90 | 91 | 相信此时大家现在对贪心算法又有一个新的认识了,加油💪 92 | 93 | 94 | 95 | 96 | 97 | 98 |

99 | -------------------------------------------------------------------------------- /problems/栈与队列理论基础.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 |

参与本项目,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!

6 | 7 | > 来看看栈和队列不为人知的一面 8 | 9 | 我想栈和队列的原理大家应该很熟悉了,队列是先进先出,栈是先进后出。 10 | 11 | 如图所示: 12 | 13 | ![栈与队列理论1](https://img-blog.csdnimg.cn/20210104235346563.png) 14 | 15 | 那么我这里在列出四个关于栈的问题,大家可以思考一下。以下是以C++为例,相信使用其他编程语言的同学也对应思考一下,自己使用的编程语言里栈和队列是什么样的。 16 | 17 | 1. C++中stack 是容器么? 18 | 2. 我们使用的stack是属于那个版本的STL? 19 | 3. 我们使用的STL中stack是如何实现的? 20 | 4. stack 提供迭代器来遍历stack空间么? 21 | 22 | 相信这四个问题并不那么好回答, 因为一些同学使用数据结构会停留在非常表面上的应用,稍稍往深一问,就会有好像懂,好像也不懂的感觉。 23 | 24 | 有的同学可能仅仅知道有栈和队列这么个数据结构,却不知道底层实现,也不清楚所使用栈和队列和STL是什么关系。 25 | 26 | 所以这里我在给大家扫一遍基础知识, 27 | 28 | 首先大家要知道 栈和队列是STL(C++标准库)里面的两个数据结构。 29 | 30 | C++标准库是有多个版本的,要知道我们使用的STL是哪个版本,才能知道对应的栈和队列的实现原理。 31 | 32 | 那么来介绍一下,三个最为普遍的STL版本: 33 | 34 | 1. HP STL 35 | 其他版本的C++ STL,一般是以HP STL为蓝本实现出来的,HP STL是C++ STL的第一个实现版本,而且开放源代码。 36 | 37 | 2. P.J.Plauger STL 38 | 由P.J.Plauger参照HP STL实现出来的,被Visual C++编译器所采用,不是开源的。 39 | 40 | 3. SGI STL 41 | 由Silicon Graphics Computer Systems公司参照HP STL实现,被Linux的C++编译器GCC所采用,SGI STL是开源软件,源码可读性甚高。 42 | 43 | 接下来介绍的栈和队列也是SGI STL里面的数据结构, 知道了使用版本,才知道对应的底层实现。 44 | 45 | 来说一说栈,栈先进后出,如图所示: 46 | 47 | ![栈与队列理论2](https://img-blog.csdnimg.cn/20210104235434905.png) 48 | 49 | 栈提供push 和 pop 等等接口,所有元素必须符合先进后出规则,所以栈不提供走访功能,也不提供迭代器(iterator)。 不像是set 或者map 提供迭代器iterator来遍历所有元素。 50 | 51 | **栈是以底层容器完成其所有的工作,对外提供统一的接口,底层容器是可插拔的(也就是说我们可以控制使用哪种容器来实现栈的功能)。** 52 | 53 | 所以STL中栈往往不被归类为容器,而被归类为container adapter(容器适配器)。 54 | 55 | 那么问题来了,STL 中栈是用什么容器实现的? 56 | 57 | 从下图中可以看出,栈的内部结构,栈的底层实现可以是vector,deque,list 都是可以的, 主要就是数组和链表的底层实现。 58 | 59 | ![栈与队列理论3](https://img-blog.csdnimg.cn/20210104235459376.png) 60 | 61 | 62 | **我们常用的SGI STL,如果没有指定底层实现的话,默认是以deque为缺省情况下栈的低层结构。** 63 | 64 | deque是一个双向队列,只要封住一段,只开通另一端就可以实现栈的逻辑了。 65 | 66 | **SGI STL中 队列底层实现缺省情况下一样使用deque实现的。** 67 | 68 | 我们也可以指定vector为栈的底层实现,初始化语句如下: 69 | 70 | ```cpp 71 | std::stack > third; // 使用vector为底层容器的栈 72 | ``` 73 | 74 | 刚刚讲过栈的特性,对应的队列的情况是一样的。 75 | 76 | 队列中先进先出的数据结构,同样不允许有遍历行为,不提供迭代器, **SGI STL中队列一样是以deque为缺省情况下的底部结构。** 77 | 78 | 也可以指定list 为起底层实现,初始化queue的语句如下: 79 | 80 | ```cpp 81 | std::queue> third; // 定义以list为底层容器的队列 82 | ``` 83 | 84 | 所以STL 队列也不被归类为容器,而被归类为container adapter( 容器适配器)。 85 | 86 | 我这里讲的都是C++ 语言中情况, 使用其他语言的同学也要思考栈与队列的底层实现问题, 不要对数据结构的使用浅尝辄止,而要深挖起内部原理,才能夯实基础。 87 | 88 | 89 | 90 | 91 | ----------------------- 92 |
93 | -------------------------------------------------------------------------------- /problems/知识星球精选/offer对比-决赛圈.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 | 6 | # offer选择进入决赛圈.md 7 | 8 | 秋招已经结束了,该开奖的差不多都陆续开奖了,很多录友的也进入了offer决赛圈。 9 | 10 | 我每天都在[知识星球](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ)里,回答十几个offer对比的问题,我也是结合自己过来人的经验给大家做做分析,我也选几个案例,在公众号上也给大家分享一下,希望对大家有所启发。 11 | 12 | 以下是知识星球里的部分问答: 13 | 14 | ![](https://code-thinking-1253855093.file.myqcloud.com/pics/20211031113844.png) 15 | 16 | C++后端开发 总包40w,这个薪资和岗位很不错了,至于干的活杂不杂 都不是你能打听出来的,要进去,看具体工作,以及领导的具体安排,只有亲自去感受了,才知道是不是打杂。 17 | 18 | 深信服 云计算 大多数是做toB的业务,做私有云,几乎是和硬件设备一起卖,和阿里云,腾讯云,这些公有云厂商不是一个概念的。 19 | 20 | 深信服也不错,但不用奔着云计算这个壳子就去冲 深信服,进去干的活未必和云计算有多关系,而且去深信服 你就能保证不打杂了么? 对吧 21 | 22 | 所以 具体工作内容是 我们控制不了的,知道个大概方向就可以了。 23 | 24 | 去百度吧,挺好的。 25 | 26 | ------------- 27 | 28 | ![](https://code-thinking-1253855093.file.myqcloud.com/pics/20211031105039.png) 29 | 30 | 普渡科技 是是一家C轮创业公司,一般创业公司 双休的可能性不太大。而且 看两家给你的薪资,如果算上公积金的话,到手的钱没有百度开的高。 31 | 32 | 应届生去创业公司,有一点吃亏,就是你刚进去,因为你还不能干活,有明显的产出,或者能力有限,并不会给你 期权甚至股份,可能股份兑现不了,但表示的是对候选人的重视程度。 33 | 34 | 创业公司研发流程还不够规范,所谓的野蛮成长 就是没有流程。 **关键是能成长起来 万事大吉,就怕长不起来**。 35 | 36 | 百度虽然是测开的岗位,但薪资开得挺高了,可以看出对你的重视,飞桨深度学习平台部,也很不错,是百度重点打造的深度学习框架。 37 | 38 | 我倾向于选百度,虽然是测开,但进去依然可以学很多东西。 这样稳一些。 39 | 40 | 当然如果你想赌一把,可以去普渡科技,谁也说不好,万一后面起飞了呢。 41 | 42 | ---------- 43 | 44 | ![](https://code-thinking-1253855093.file.myqcloud.com/pics/20211031111110.png) 45 | 46 | 双非本,还是电子信息类专业,能拿到这些offer,真的很不容易了👍 47 | 48 | 如果喜欢搞硬件,嵌入式应用方向其实也挺宽的,需求面也很广,华为 中兴,还有一堆手机厂商 新能源车企,智能家居,涉及到物联网的行业,都需要嵌入式开发。 49 | 50 | 中新赛克 也是上市公司,其实和 海康威视 大华股份 都差不多,这几家给薪资都差不多,一样的薪资,你在南京可比在杭州舒服多了啊,而且你家也在南京。 51 | 52 | 如果要真的是去大厂学技术,或者工资特别高,背井离乡也是可以的,但 海康威视 大华股份 估计也没有达到这个程度,薪资也没高出来,甚至可能不如 中新赛克 ,你还有 中新赛克给你的签字费呢。 53 | 54 | 综上,我倾向于 去 中新赛克,在老家,这个薪资不挺舒服的么,南京也很不错。 好好干吧💪 55 | 56 | ------------- 57 | 58 | ![](https://code-thinking-1253855093.file.myqcloud.com/pics/20211031110153.png) 59 | 60 | 腾讯 这个部门有点边缘,技术栈比较浅。企业IT部就是做 企业内部应用的,最多也就是 几万人使用吧,大概率也没有机会磨练技术。系统很成熟,当然不加班。 61 | 62 | 百度推荐架构部,还是挺核心的,技术能力 还是比较强的。 **在上海应届生可以落户了,比深圳户口香太多太多了**。 63 | 64 | 至于晋升,百度晋升 一点也不慢,顺利的话,T3 到 T6 可以三年,一般情况是4年, T6跳 腾讯可以对应的是3-1 或者 3-2级别了。 65 | 66 | 至于光环,对个人来说,百度工程师在业内是很受认可的,一点不比腾讯差, 很多人说:拼多多啊,京东啊 市值都超过百度了,百度不是第一梯队了,等等。 67 | 68 | 说实话,**那公司的市值和我们这些码农有关系么**,对吧,**我们对关心的是 自己技术的成长,自己值多少钱,而不是公司值多少钱**。 69 | 70 | 至于薪资,相对于岗位,一年差6w,不算多,倾向于选百度。 71 | 72 | ------------- 73 | 74 | ![](https://code-thinking-1253855093.file.myqcloud.com/pics/20211031105736.png) 75 | 76 | 去字节吧, 云存储方向 这个方向值得深耕, 是一个技术驱动的方向,而且各大厂商 都搞分布式存储,就业机会挺多的,再说 字节给的薪资也不错。 77 | 78 | 如果以后想离家近,你可以跳槽 腾讯云 继续做分布式存储,薪资还能涨一波。 79 | 80 | 如果对技术有追求的话,整个技术生涯都是可以认准云存储方向。存储是刚需! 81 | 82 | 你可别在准备春招了,这大厂offer 都不要,准备啥 春招啊,哈哈哈,别卷了,休息吧。 83 | 84 | ---------- 85 | 86 | 以上就是我在知识星球,针对录友们offer决赛圈的解答,希望对大家也有所帮助。 87 | 88 | -------------------------------------------------------------------------------- /problems/知识星球精选/秋招下半场依然没offer.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 | 6 | # 秋招下半场依然没offer,怎么办? 7 | 8 | [知识星球](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ)里一些录友拿到了满意的offer,也有一些录友,依然没有offer,每天的状态已经不能用焦虑来形容了。 9 | 10 | 在星球里就有录友向我提问了这样一个问题: 11 | 12 | ![](https://code-thinking-1253855093.file.myqcloud.com/pics/20210921103222.png) 13 | 14 | 估计还有公众号上还有很多录友也是这种情况,马上面试,但总感觉哪里都还没准备好,然后还必须要面试,每次面试结果还不理想。 15 | 16 | 能感受到此时大家非常迫切要知道还有没有什么切实可行的方案 ,只要执行 ,就能拿到offer。 17 | 18 | 恨不得提前知道面试官的问题,然后把问题都背下来得了。。。。 19 | 20 | 其实我是非常理解大家的心情的,这个时候怪自己准备的太晚也没有用。 21 | 22 | 说实话,已经是秋招下半场(接近末尾了),**已经没有针对面试的复习方案了。什么学习路线,突击计划 在这个时候 都没啥作用了**。 23 | 24 | 现在什么最重要呢? 25 | 26 | 是**心态**。 27 | 28 | 心态要稳住,**放低预期,但别放低努力的程度**。 29 | 30 | 估计参加过面试的同学,都会有这种感觉,面试前一天复习,突击的内容,**第二天面试都不会考!是的,一道都不会考!** 31 | 32 | 那么为什么还学呢? 33 | 34 | 就是这股劲不能泄,只要憋住劲,每天面试,复盘,学习,面试再复盘,再学习,最终大家其实都能拿到offer的,只不过是offer的满意程度罢了。 35 | 36 | **如果泄了劲,那就真没戏了**。 37 | 38 | **可能自暴自弃两天,然后就发现自己啥也学不进去了**。 39 | 40 | 所以这个时候了,算法题还要一直刷,八股文也要背起来。 41 | 42 | 讲真,现在刷的题,看的八股文,面试可能也不一定会考,但为什么还要看呢,**就是稳定心态**。 43 | 44 | **剩下的就看缘分了!** 45 | 46 | 面试挺看缘分的, 可能一个面试官对你的评价就是基础不牢,下一家公司面试官对你的评价就是 基础不错,但项目经验不足。 47 | 48 | 所以此时你自己都蒙了,究竟自己是 基础不牢,还是项目经验不足呢? 49 | 50 | 其实面试的本质,面试官主观性还是比较强的,可能就是问的几个问题 你都背过,而且背的很深入,那评价就是基础牢了呗。 51 | 52 | 53 | ## 在学点技术,冲春招? 54 | 55 | [知识星球](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ)里还有一位录友,也是类似的情况,秋招感觉很艰难,要不要在学一学微服务分布式之类的,再冲春招。 56 | 57 | ![](https://code-thinking-1253855093.file.myqcloud.com/pics/20210921103343.png) 58 | 59 | 其实这个时候,大家也不要再心思学点什么新技术,增加自己的筹码了。 60 | 61 | 还是那句话,**现在学啥,面试也未必会考!** 62 | 63 | 就算 现在不参加秋招了,去学 微服务了,分布式。面试的时候 ,面试官未必会考不说,而且 你也未必学的透彻。 64 | 65 | 再说,春招的岗位 很少,而且优质岗位更少。 66 | 67 | 所以大家这个时候,就不要等了。 68 | 69 | **直接海投,面试,复盘总结,再面试**。 70 | 71 | 72 | ## 给参加明年秋招录友的劝告 73 | 74 | 其实我在[知识星球](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ)里,**看到了太多太多 参加今年秋招的录友 埋怨自己 准备的太晚了,没想到要看的东西这么多,没想到竞争这么激烈**。 75 | 76 | 所以明年参加秋招的录友,要提前就开始准备,明确自己的岗位,知道岗位的要求,制定自己的计划,然后按计划执行。 77 | 78 | **其实多早开始准备,都不算早!** 79 | 80 | 很多在[知识星球](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ)里的准大三,研一的录友,都能在星球里感受到 秋招的竞争与激烈。 81 | 82 | 所以他们也就早早的开始准备了。 83 | 84 | 来看看星球里 这位录友的提问,**他也才刚刚准大三,就已经为明年的秋招开始精心准备了**。 85 | 86 | ![](https://code-thinking-1253855093.file.myqcloud.com/pics/20210920222600.png) 87 | 88 | 估计大多数准大三或者准研一的同学都还没有这种意识。 89 | 90 | **但在[知识星球](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ)里,通过每天录友们的打卡,每天都能感受到这种紧迫感**。 91 | 92 | 正如一位星球里的录友这么说: 93 | 94 | ![](https://code-thinking-1253855093.file.myqcloud.com/pics/20210920223847.png) 95 | 96 | 很多录友加入星球之后,**刷贴吧刷剧已经不香了,只有刷星球!** 97 | 98 | 感觉每天自己被push上去,其实有时候 **大家需要的就是一个氛围,自己一个人很难有提前准备的意识,也很难坚持下来**。 99 | 100 | -------------------------------------------------------------------------------- /problems/前序/vim.md: -------------------------------------------------------------------------------- 1 | # 人生苦短,我用VIM! 2 | 3 | 熟悉我的录友,应该都知道我是vim流,无论是写代码还是写文档(Markdown),都是vim,都没用IDE。 4 | 5 | 但这里我并不是说IDE不好用,IDE在 代码跟踪,引用跳转等等其实是很给力的,效率比vim高。 6 | 7 | 我用vim的话,如果需要跟踪代码的话,就用ctag去跳转,虽然很不智能(是基于规则匹配,不是语义匹配),但加上我自己的智能就也能用(这里真的要看对代码的把握程度了,哈哈哈) 8 | 9 | 所以连跟踪代码都不用IDE的话,其他方面那我就更用不上IDE了。 10 | 11 | ## 为什么用VIM 12 | 13 | **至于写代码的效率,VIM完爆IDE**,其他不说,就使用IDE每次还要去碰鼠标,就很让人烦心!(真凸显了程序员的执着) 14 | 15 | 这里说一说vim的方便之处吧,搞后端开发的同学,都得玩linux吧,在linux下写代码,如果不会vim的话,会非常难受。 16 | 17 | 日常我们的开发机,线上服务器,预发布服务器,都是远端linux,需要跳板机连上去,进行操作,如果不会vim,每次都把代码拷贝到本地,修改编译,在传到远端服务器,还真的麻烦。 18 | 19 | 使用VIM的话,本地,服务器,开发机,一刀流,无缝切换,爽不。 20 | 21 | IDE那么很吃内存,打开个IDE卡半天,用VIM就很轻便了,秒开有木有! 22 | 23 | 而且在我们日常开发中,工作年头多了,都会发现没有纯粹的C++,Java开发啥的,就是 C++也得写,Java也得写,有时候写Go起个http服务,写Python处理一下数据,写shell搞个自动部署,编译啥的。 **总是就是啥语言就得写,一些以项目需求为导向!** 24 | 25 | 写语言还要切换不同的IDE,熟悉不同的操作姿势,想想是不是很麻烦。 26 | 27 | 听说好像现在有的IDE可以支持很多语言了,这个我还不太了解,但能确定的是,IDE支持的语言再多,也不会有vim多。 28 | 29 | **因为vim是编辑器!**,什么都可以写,不同的语言做一下相应的配置就好,写起来都是一样的顺畅。 30 | 31 | 应该不少录友感觉vim上快捷键太多了,根本记不过来,其实这和我看IDE是一样的想法,我看IDE上哪些按钮一排一排的也太多了,我都记不过来,所以索性一套vim流 扫遍所有代码,它不香么。 32 | 33 | 而且IDE集成编译、调试、智能补全、语法高亮、工程管理等等,隐藏了太多细节,使用vim,就都自己配置,想支持什么语言就自己配置,想怎么样就怎么样,需要什么就补什么,这不是很酷么? 34 | 35 | 可能有的同学感觉什么都要自己配置,有点恐惧。但一旦配置好的就非常舒服了。 36 | 37 | **其实工程师就要逢山开路遇水搭桥,这也是最基本的素质!** 38 | 39 | 从头打在一个自己的开发利器,再舒服不过了。 40 | 41 | ## PowerVim 42 | 43 | 这里给大家介绍一下我的vim配置吧,**这套vim配置我已经打磨了将近四年**,不断调整优化,已经可以完全满足工业级打开的需求了。 44 | 45 | 所以我给它起名为PowerVim。一个真正强大的vim。 46 | 47 | ``` 48 | _____ __ ___ 49 | | __ \ \ \ / (_) 50 | | |__) |____ _____ _ _\ \ / / _ _ __ ___ 51 | | ___/ _ \ \ /\ / / _ \ '__\ \/ / | | '_ ` _ \ 52 | | | | (_) \ V V / __/ | \ / | | | | | | | 53 | |_| \___/ \_/\_/ \___|_| \/ |_|_| |_| |_| 54 | ``` 55 | 56 | 这个配置我开源在Github上,地址:https://github.com/youngyangyang04/PowerVim 57 | 58 | 59 | 60 | 来感受一下PowerVim的使用体验,看起来很酷吧!注意这些操作都不用鼠标的,一波键盘控制流!所以我平时写代码是不碰鼠标的! 61 | 62 | ![](https://code-thinking.cdn.bcebos.com/gifs/vim_overview.gif) 63 | 64 | ## 安装 65 | 66 | PowerVim的安防非常简单,我已经写好了安装脚本,只要执行以下就可以安装,而且不会影响你之前的vim配置,之前的配置都给做了备份,大家看一下脚本就知道备份在哪里了。 67 | 68 | 安装过程非常简单: 69 | ```bash 70 | git clone https://github.com/youngyangyang04/PowerVim.git 71 | cd PowerVim 72 | sh install.sh 73 | ``` 74 | 75 | ## 特性 76 | 77 | 目前PowerVim支持如下功能,这些都是自己配置的: 78 | 79 | * CPP、PHP、JAVA代码补全,如果需要其他语言补全,可自行配置关键字列表在PowerVim/.vim/dictionary目录下 80 | * 显示文件函数变量列表 81 | * MiniBuf显示打开过的文件 82 | * 语法高亮支持C++ (including C++11)、 Go、Java、 Php、 Html、 Json 和 Markdown 83 | * 显示git状态,和主干或分支的添加修改删除的情况 84 | * 显示项目文件目录,方便快速打开 85 | * 快速注释,使用gcc注释当前行,gc注释选中的块 86 | * 项目内搜索关键字和文件夹 87 | * 漂亮的颜色搭配和状态栏显示 88 | 89 | ## 最后 90 | 91 | 当然 还有很多,我还详细写了PowerVim的快捷键,使用方法,插件,配置,等等,都在Github主页的README上。当时我的Github上写的都是英文README,这次为了方便大家阅读,我又翻译成中文README。 92 | 93 | ![](https://code-thinking-1253855093.file.myqcloud.com/pics/20211013102249.png) 94 | 95 | 96 | 最后,因为这个vim配置因为我一直没有宣传,所以star数量很少,哈哈哈,录友们去给个star吧,真正的开发利器,值得顶起来! 97 | 98 | -------------------------------------------------------------------------------- /problems/知识星球精选/offer总决赛,何去何从.md: -------------------------------------------------------------------------------- 1 | 2 |

3 | 4 | 5 | 6 | 7 | # offer总决赛,何去何从! 8 | 9 | 最近在[知识星球](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ)上,给至少300位录友做了offer选择,准对大家的情况,结合我的经验做一做分析。 10 | 11 | 希望可以给大家带来不一样的分析视角,帮大家少走弯路。 12 | 13 | 以下是我在知识星球里分析的部分案例,公众号上再给大家分享一波。 14 | 15 | ----------- 16 | 17 | ![](https://code-thinking-1253855093.file.myqcloud.com/pics/20211108102416.png) 18 | 19 | 1. C++ 后端,客户端,测开,指定选 C++后端啊,这是送分题。 20 | 2. 转型的问题不好回答,各有各的出路,**就算大厂里,95%以上的程序员都不想写代码,就想指点江山**,但为什么大家都在写代码呢,因为出路没有固定的公式,没有固定的方法,很多人完美转型看的是运气,看时机,也看努力,**但最重要的是运气和时机**。 最不缺的就是努力的人,其实大家都挺努力的。 21 | 3. 不会的,大厂里也没有一家语言独大,这种担心没必要。 22 | 4. 不同公司处理情况不一样,甚至每年都会变,大部分都不会黑名单,你这几家都不会。 23 | 5. 你的担心有点过头了,既然你拿到的offer就要对自己有信心,你也不是走后门拿到的offer,对自己能力这么没信心么,进去之后好好干就好了。剩下的交给缘分。 计划的在周密都没有变化快。 24 | 6. 你问的太全面了[捂脸],我都没想到 拿到大厂offer,能但担心出来 这么多事情。已经很周密了👍 25 | 26 | 最后 倾向于你去阿里云吧,这么好的的机会 有啥犹豫的。 27 | 28 | 29 | ----------------- 30 | 31 | 32 | ![](https://code-thinking-1253855093.file.myqcloud.com/pics/20211108103414.png) 33 | 34 | 我感觉你不用不甘心大白菜,其实挺好的,客观来看 非科班转码 拿腾信后端开发的 offer 挺不错的。 35 | 36 | 虾皮在公司影响力上 和 腾讯不是一个数量级的。 37 | 38 | 跳槽虽然看base,但也看公司的,腾讯光环加持 比 虾皮可有力多了。 39 | 40 | 腾讯的总包是有点虚(花样有点多),但第一年到 43w了 挺不错的,腾讯好好干,升到高级工程师,在外年很值钱的。 现在这点钱也不算啥。**而且现在应届生薪资真的挺高的,不用在去追高,容易摔到的**。 41 | 42 | 我建议你直接去腾讯就好, 这个选择题 其实挺好选的。 43 | 44 | ------------- 45 | 46 | ![](https://code-thinking-1253855093.file.myqcloud.com/pics/20211108103835.png) 47 | 48 | 广州没有百度吧,可以活水到深圳百度,工位很宽敞,比北京工位舒服多了。 49 | 50 | 我倾向于选百度吧,而且百度的岗位也不错,薪资也比 虎牙高(虎牙的股票价值不好说),**虎牙你听说是 965 但未必是 965,可能你已入职项目就忙起来了,瞬间996,这个工作强度都不是永恒的,都是跟着项目走**。 51 | 52 | 广州可选择的互联网公司不错的,你去广州虎牙,一旦离职 其实不太好选下一家。 53 | 54 | 百度 试用期不过,这个感觉有点谣言,哪家大厂都有试用期不过的,不过这个看项目组,整体来说 基本试用期都能过,问题不大。 55 | 56 | 虾皮还在抽盲盒,就不考虑了。 57 | 58 | 去百度吧,好好锻炼几年,然后再找机会 回南方。或者transfer 深圳 也不错。 59 | 60 | ------------ 61 | 62 | ![](https://code-thinking-1253855093.file.myqcloud.com/pics/20211108104558.png) 63 | 64 | 1. 公积金可以提出来 80%,包括自己交的和公司交的,还是挺方便的,现在支付宝可以一键提取。剩下的等你买房之后 可以全部提取。 65 | 66 | 2. 如果先去腾讯的话,你去 字节 做客户端更合适一些,而且你还是做 游戏直播的客户端,和腾讯互娱还是很匹配的。 67 | 68 | 至于研究生做客户端亏了 的问题,其实 95% 的研究生 基本都是做研发,后端或者客户端。 69 | 70 | 确实很多人感觉 读个研究生不做算法,不搞AI,和本科生没啥区别,**但事实是 搞算法 搞AI 可能都找不到工作了,那么就没有必要有这个执念**。 71 | 72 | 你现在能拿到 字节offer,也有你是研究生的加持 ,虽然 学历不等于能力,但 人多而卷,用学历晒人是最高效的方式。 73 | 74 | ------------ 75 | 76 | ![](https://code-thinking-1253855093.file.myqcloud.com/pics/20211108104735.png) 77 | 78 | 79 | 1. 一般来说管培计划,都是培养企业未来高管的,是很不错的,不同原员工干到高管多难,**但如果参加管培计划,那就不一样的,资源 和 机会 要不正常员工 多很多**, 从 去哪给你的薪资和签字费就能看出来。 不过去哪网的管培其实我不了解,我只是说一说普遍管培的情况。 80 | 81 | 2. 小米有很多东西可以学习? 这个其实 你现在是应届生,去哪家公司 都有很多东西可以学习,这个看具体内容了。 82 | 3. 我感觉不用了吧,这offer也不错啊,当然如果还有激情,再战也可以的。毕竟没啥损失,不过感觉可以休息了,躺平吧。 83 | 84 | 建议再去详细了解一下 去哪网管培计划 的具体内容,因为不同公司 管培计划不太一样,你是 技术岗管培 还是其他方向管培。 85 | 86 | 87 | 以上就是我在知识星球,针对录友们offer决赛圈的解答,希望对大家也有所帮助。 88 | 89 | -------------------------------------------------------------------------------- /problems/前序/北京互联网公司总结.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 | 6 |

7 |

欢迎大家参与本项目,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!

8 | 9 | 10 | 11 | # 北京互联网公司总结 12 | 13 | **个人总结难免有所疏忽,欢迎大家补充,公司好坏没有排名哈!** 14 | 15 | 如果要在北京找工作,这份list可以作为一个大纲,寻找自己合适的公司。 16 | 17 | ## 一线互联网 18 | 19 | * 百度(总部) 20 | * 阿里(北京) 21 | * 腾讯(北京) 22 | * 字节跳动(总部) 23 | 24 | ## 外企 25 | 26 | * 微软(北京)微软中国主要就是北京和苏州 27 | * Hulu(北京)美国的视频网站,听说福利待遇超级棒 28 | * Airbnb(北京)房屋租赁平台 29 | * Grab(北京)东南亚第一大出行 App 30 | * 印象笔记(北京)evernote在中国的独立品牌 31 | * FreeWheel(北京)美国最大的视频广告管理和投放平台 32 | * amazon(北京)全球最大的电商平台 33 | 34 | ## 二线互联网 35 | 36 | * 美团点评(总部) 37 | * 京东(总部) 38 | * 网易(北京) 39 | * 滴滴出行(总部) 40 | * 新浪(总部) 41 | * 快手(总部) 42 | * 搜狐(总部) 43 | * 搜狗(总部) 44 | * 360(总部) 45 | 46 | ## 硬件巨头 (有软件/互联网业务) 47 | 48 | * 华为(北京) 49 | * 联想(总部) 50 | * 小米(总部)后序要搬到武汉,互联网业务也是小米重头 51 | 52 | ## 三线互联网 53 | 54 | * 爱奇艺(总部) 55 | * 去哪儿网(总部) 56 | * 知乎(总部) 57 | * 豆瓣(总部) 58 | * 当当网(总部) 59 | * 完美世界(总部)游戏公司 60 | * 昆仑万维(总部)游戏公司 61 | * 58同城(总部) 62 | * 陌陌(总部) 63 | * 金山软件(北京)包括金山办公软件 64 | * 用友网络科技(总部)企业服务ERP提供商 65 | * 映客直播(总部) 66 | * 猎豹移动(总部) 67 | * 一点资讯(总部) 68 | * 国双(总部)企业级大数据和人工智能解决方案提供商 69 | 70 | ## 明星创业公司 71 | 72 | 可以发现北京一堆在线教育的公司,可能教育要紧盯了政策变化,所以都要在北京吧 73 | 74 | * 好未来(总部)在线教育 75 | * 猿辅导(总部)在线教育 76 | * 跟谁学(总部)在线教育 77 | * 作业帮(总部)在线教育 78 | * VIPKID(总部)在线教育 79 | * 雪球(总部)股市资讯 80 | * 唱吧(总部) 81 | * 每日优鲜(总部)让每个人随时随地享受食物的美好 82 | * 微店(总部) 83 | * 罗辑思维(总部)得到APP 84 | * 值得买科技(总部)让每一次消费产生幸福感 85 | * 拉勾网(总部)互联网招聘 86 | 87 | ## AI独角兽公司 88 | 89 | * 商汤科技(总部)专注于计算机视觉和深度学习 90 | * 旷视科技(总部)人工智能产品和解决方案公司 91 | * 第四范式(总部)人工智能技术与服务提供商 92 | * 地平线机器人(总部)边缘人工智能芯片的全球领导者 93 | * 寒武纪(总部)全球智能芯片领域的先行者 94 | 95 | ## 互联网媒体 96 | 97 | * 央视网 98 | * 搜房网 99 | * 易车网 100 | * 链家网 101 | * 自如网 102 | * 汽车之家 103 | 104 | ## 总结 105 | 106 | 可能是我写总结写习惯了,什么文章都要有一个总结,哈哈,那么我就总结一下。 107 | 108 | 北京的互联网氛围绝对是最好的(暂不讨论户口和房价问题),大家如果看了[深圳原来有这么多互联网公司,你都知道么?](https://programmercarl.com/前序/深圳互联网公司总结.html)这篇之后,**会发现北京互联网外企和二线互联网公司数量多的优势,在深圳的互联网公司断档比较严重,如果去不了为数不多的一线公司,可选择的余地就非常少了,而北京选择的余地就很多!** 109 | 110 | 相对来说,深圳的硬件企业更多一些,因为珠三角制造业配套比较完善。而大多数互联网公司其实就是媒体公司,当然要靠近政治文化中心,这也是有原因的。 111 | 112 | 就酱,我也会陆续整理其他城市的互联网公司,希望对大家有所帮助。 113 | 114 | 115 | 116 | 117 | 118 | ----------------------- 119 |
120 | -------------------------------------------------------------------------------- /problems/链表总结篇.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 |

参与本项目,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!

6 | 7 | 8 | 9 | ## 链表的理论基础 10 | 11 | 在这篇文章[关于链表,你该了解这些!](https://programmercarl.com/链表理论基础.html)中,介绍了如下几点: 12 | 13 | * 链表的种类主要为:单链表,双链表,循环链表 14 | * 链表的存储方式:链表的节点在内存中是分散存储的,通过指针连在一起。 15 | * 链表是如何进行增删改查的。 16 | * 数组和链表在不同场景下的性能分析。 17 | 18 | **可以说把链表基础的知识都概括了,但又不像教科书那样的繁琐**。 19 | 20 | ## 链表经典题目 21 | 22 | ### 虚拟头结点 23 | 24 | 在[链表:听说用虚拟头节点会方便很多?](https://programmercarl.com/0203.移除链表元素.html)中,我们讲解了链表操作中一个非常总要的技巧:虚拟头节点。 25 | 26 | 链表的一大问题就是操作当前节点必须要找前一个节点才能操作。这就造成了,头结点的尴尬,因为头结点没有前一个节点了。 27 | 28 | **每次对应头结点的情况都要单独处理,所以使用虚拟头结点的技巧,就可以解决这个问题**。 29 | 30 | 在[链表:听说用虚拟头节点会方便很多?](https://programmercarl.com/0203.移除链表元素.html)中,我给出了用虚拟头结点和没用虚拟头结点的代码,大家对比一下就会发现,使用虚拟头结点的好处。 31 | 32 | ### 链表的基本操作 33 | 34 | 在[链表:一道题目考察了常见的五个操作!](https://programmercarl.com/0707.设计链表.html)中,我们通设计链表把链表常见的五个操作练习了一遍。 35 | 36 | 这是练习链表基础操作的非常好的一道题目,考察了: 37 | 38 | * 获取链表第index个节点的数值 39 | * 在链表的最前面插入一个节点 40 | * 在链表的最后面插入一个节点 41 | * 在链表第index个节点前面插入一个节点 42 | * 删除链表的第index个节点的数值 43 | 44 | **可以说把这道题目做了,链表基本操作就OK了,再也不用担心链表增删改查整不明白了**。 45 | 46 | 这里我依然使用了虚拟头结点的技巧,大家复习的时候,可以去看一下代码。 47 | 48 | ### 反转链表 49 | 50 | 在[链表:听说过两天反转链表又写不出来了?](https://programmercarl.com/0206.翻转链表.html)中,讲解了如何反转链表。 51 | 52 | 因为反转链表的代码相对简单,有的同学可能直接背下来了,但一写还是容易出问题。 53 | 54 | 反转链表是面试中高频题目,很考察面试者对链表操作的熟练程度。 55 | 56 | 我在[文章](https://programmercarl.com/0206.翻转链表.html)中,给出了两种反转的方式,迭代法和递归法。 57 | 58 | 建议大家先学透迭代法,然后再看递归法,因为递归法比较绕,如果迭代还写不明白,递归基本也写不明白了。 59 | 60 | **可以先通过迭代法,彻底弄清楚链表反转的过程!** 61 | 62 | ### 删除倒数第N个节点 63 | 64 | 在[链表:删除链表倒数第N个节点,怎么删?](https://programmercarl.com/0019.删除链表的倒数第N个节点.html)中我们结合虚拟头结点 和 双指针法来移除链表倒数第N个节点。 65 | 66 | 67 | ### 链表相交 68 | 69 | [链表:链表相交](https://programmercarl.com/面试题02.07.链表相交.html)使用双指针来找到两个链表的交点(引用完全相同,即:内存地址完全相同的交点) 70 | 71 | ## 环形链表 72 | 73 | 在[链表:环找到了,那入口呢?](https://programmercarl.com/0142.环形链表II.html)中,讲解了在链表如何找环,以及如何找环的入口位置。 74 | 75 | 这道题目可以说是链表的比较难的题目了。 但代码却十分简洁,主要在于一些数学证明。 76 | 77 | ## 总结 78 | 79 | 考察链表的操作其实就是考察指针的操作,是面试中的常见类型。 80 | 81 | 链表篇中开头介绍[链表理论知识](https://programmercarl.com/0203.移除链表元素.html),然后分别通过经典题目介绍了如下知识点: 82 | 83 | 1. [关于链表,你该了解这些!](https://programmercarl.com/链表理论基础.html) 84 | 2. [虚拟头结点的技巧](https://programmercarl.com/0203.移除链表元素.html) 85 | 3. [链表的增删改查](https://programmercarl.com/0707.设计链表.html) 86 | 4. [反转一个链表](https://programmercarl.com/0206.翻转链表.html) 87 | 5. [删除倒数第N个节点](https://programmercarl.com/0019.删除链表的倒数第N个节点.html) 88 | 6. [链表相交](https://programmercarl.com/面试题02.07.链表相交.html) 89 | 7. [有否环形,以及环的入口](https://programmercarl.com/0142.环形链表II.html) 90 | 91 | 92 | 93 | 94 | 95 | ----------------------- 96 |
97 | -------------------------------------------------------------------------------- /problems/周总结/20201217贪心周末总结.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 本周小结!(贪心算法系列三) 4 | 5 | 对于贪心,大多数同学都会感觉,不就是常识嘛,这算啥算法,那么本周的题目就可以带大家初步领略一下贪心的巧妙,贪心算法往往妙的出其不意。 6 | 7 | ## 周一 8 | 9 | 在[贪心算法:加油站](https://programmercarl.com/0134.加油站.html)中给出每一个加油站的汽油和开到这个加油站的消耗,问汽车能不能开一圈。 10 | 11 | 这道题目咋眼一看,感觉是一道模拟题,模拟一下汽车从每一个节点出发看看能不能开一圈,时间复杂度是$O(n^2)$。 12 | 13 | 即使用模拟这种情况,也挺考察代码技巧的。 14 | 15 | **for循环适合模拟从头到尾的遍历,而while循环适合模拟环形遍历,对于本题的场景要善于使用while!** 16 | 17 | 如果代码功力不到位,就模拟这种情况,可能写的也会很费劲。 18 | 19 | 本题的贪心解法,我给出两种解法。 20 | 21 | 对于解法一,其实我并不认为这是贪心,因为没有找出局部最优,而是直接从全局最优的角度上思考问题,但思路很巧妙,值得学习一下。 22 | 23 | 对于解法二,贪心的局部最优:当前累加rest[j]的和curSum一旦小于0,起始位置至少要是j+1,因为从j开始一定不行。全局最优:找到可以跑一圈的起始位置。 24 | 25 | 这里是可以从局部最优推出全局最优的,想不出反例,那就试试贪心。 26 | 27 | **解法二就体现出贪心的精髓,同时大家也会发现,虽然贪心是常识,有些常识并不容易,甚至很难!** 28 | 29 | ## 周二 30 | 31 | 在[贪心算法:分发糖果](https://programmercarl.com/0135.分发糖果.html)中我们第一次接触了需要考虑两个维度的情况。 32 | 33 | 例如这道题,是先考虑左边呢,还是考虑右边呢? 34 | 35 | **先考虑哪一边都可以! 就别两边一起考虑,那样就把自己陷进去了**。 36 | 37 | 先贪心一边,局部最优:只要右边评分比左边大,右边的孩子就多一个糖果,全局最优:相邻的孩子中,评分高的右孩子获得比左边孩子更多的糖果 38 | 39 | 如图: 40 | ![135.分发糖果](https://img-blog.csdnimg.cn/20201117114916878.png) 41 | 42 | 43 | 接着在贪心另一边,左孩子大于右孩子,左孩子的糖果就要比右孩子多。 44 | 45 | 此时candyVec[i](第i个小孩的糖果数量,左孩子)就有两个选择了,一个是candyVec[i + 1] + 1(从右孩子这个加1得到的糖果数量),一个是candyVec[i](之前比较右孩子大于左孩子得到的糖果数量)。 46 | 47 | 那么第二次贪心的局部最优:取candyVec[i + 1] + 1 和 candyVec[i] 最大的糖果数量,保证第i个小孩的糖果数量即大于左边的也大于右边的。全局最优:相邻的孩子中,评分高的孩子获得更多的糖果。 48 | 49 | 局部最优可以推出全局最优。 50 | 51 | 如图: 52 | ![135.分发糖果1](https://img-blog.csdnimg.cn/20201117115658791.png) 53 | 54 | 55 | ## 周三 56 | 57 | 在[贪心算法:柠檬水找零](https://programmercarl.com/0860.柠檬水找零.html)中我们模拟了买柠檬水找零的过程。 58 | 59 | 这道题目刚一看,可能会有点懵,这要怎么找零才能保证完整全部账单的找零呢? 60 | 61 | **但仔细一琢磨就会发现,可供我们做判断的空间非常少!** 62 | 63 | 美元10只能给账单20找零,而美元5可以给账单10和账单20找零,美元5更万能! 64 | 65 | 局部最优:遇到账单20,优先消耗美元10,完成本次找零。全局最优:完成全部账单的找零。 66 | 67 | 局部最优可以推出全局最优。 68 | 69 | 所以把能遇到的情况分析一下,只要分析到具体情况了,一下子就豁然开朗了。 70 | 71 | 这道题目其实是一道简单题,但如果一开始就想从整体上寻找找零方案,就会把自己陷进去,各种情况一交叉,只会越想越复杂了。 72 | 73 | ## 周四 74 | 75 | 在[贪心算法:根据身高重建队列](https://programmercarl.com/0406.根据身高重建队列.html)中,我们再一次遇到了需要考虑两个维度的情况。 76 | 77 | 之前我们已经做过一道类似的了就是[贪心算法:分发糖果](https://programmercarl.com/0135.分发糖果.html),但本题比分发糖果难不少! 78 | 79 | [贪心算法:根据身高重建队列](https://programmercarl.com/0406.根据身高重建队列.html)中依然是要确定一边,然后在考虑另一边,两边一起考虑一定会蒙圈。 80 | 81 | 那么本题先确定k还是先确定h呢,也就是究竟先按h排序呢,还先按照k排序呢? 82 | 83 | 这里其实很考察大家的思考过程,如果按照k来从小到大排序,排完之后,会发现k的排列并不符合条件,身高也不符合条件,两个维度哪一个都没确定下来。 84 | 85 | **所以先从大到小按照h排个序,再来贪心k**。 86 | 87 | 此时局部最优:优先按身高高的people的k来插入。插入操作过后的people满足队列属性。全局最优:最后都做完插入操作,整个队列满足题目队列属性。 88 | 89 | 局部最优可以推出全局最优,找不出反例,那么就来贪心。 90 | 91 | ## 总结 92 | 93 | 「代码随想录」里已经讲了十一道贪心题目了,大家可以发现在每一道题目的讲解中,我都是把什么是局部最优,和什么是全局最优说清楚。 94 | 95 | 虽然有时候感觉贪心就是常识,但如果真正是常识性的题目,其实是模拟题,就不是贪心算法了!例如[贪心算法:加油站](https://programmercarl.com/0134.加油站.html)中的贪心方法一,其实我就认为不是贪心算法,而是直接从全局最优的角度上来模拟,因为方法里没有体现局部最优的过程。 96 | 97 | 而且大家也会发现,贪心并没有想象中的那么简单,贪心往往妙的出其不意,触不及防!哈哈 98 | 99 | 100 |
101 | -------------------------------------------------------------------------------- /problems/周总结/20201112回溯周末总结.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 本周小结!(回溯算法系列三) 4 | 5 | ## 周一 6 | 7 | 在[回溯算法:求子集问题(二)](https://programmercarl.com/0090.子集II.html)中,开始针对子集问题进行去重。 8 | 9 | 本题就是[回溯算法:求子集问题!](https://programmercarl.com/0078.子集.html)的基础上加上了去重,去重我们在[回溯算法:求组合总和(三)](https://programmercarl.com/0040.组合总和II.html)也讲过了。 10 | 11 | 所以本题对大家应该并不难。 12 | 13 | 树形结构如下: 14 | 15 | ![90.子集II](https://img-blog.csdnimg.cn/2020111217110449.png) 16 | 17 | ## 周二 18 | 19 | 在[回溯算法:递增子序列](https://programmercarl.com/0491.递增子序列.html)中,处处都能看到子集的身影,但处处是陷阱,值得好好琢磨琢磨! 20 | 21 | 树形结构如下: 22 | ![491. 递增子序列1](https://img-blog.csdnimg.cn/20201112170832333.png) 23 | 24 | [回溯算法:递增子序列](https://programmercarl.com/0491.递增子序列.html)留言区大家有很多疑问,主要还是和[回溯算法:求子集问题(二)](https://programmercarl.com/0090.子集II.html)混合在了一起。 25 | 26 | 详细在[本周小结!(回溯算法系列三)续集](https://mp.weixin.qq.com/s/kSMGHc_YpsqL2j-jb_E_Ag)中给出了介绍! 27 | 28 | ## 周三 29 | 30 | 我们已经分析了组合问题,分割问题,子集问题,那么[回溯算法:排列问题!](https://programmercarl.com/0046.全排列.html) 又不一样了。 31 | 32 | 排列是有序的,也就是说[1,2] 和[2,1] 是两个集合,这和之前分析的子集以及组合所不同的地方。 33 | 34 | 可以看出元素1在[1,2]中已经使用过了,但是在[2,1]中还要在使用一次1,所以处理排列问题就不用使用startIndex了。 35 | 36 | 如图: 37 | ![46.全排列](https://img-blog.csdnimg.cn/20201112170304979.png) 38 | 39 | **大家此时可以感受出排列问题的不同:** 40 | 41 | * 每层都是从0开始搜索而不是startIndex 42 | * 需要used数组记录path里都放了哪些元素了 43 | 44 | ## 周四 45 | 46 | 排列问题也要去重了,在[回溯算法:排列问题(二)](https://programmercarl.com/0047.全排列II.html)中又一次强调了“树层去重”和“树枝去重”。 47 | 48 | 树形结构如下: 49 | 50 | ![47.全排列II1](https://img-blog.csdnimg.cn/20201112171930470.png) 51 | 52 | **这道题目神奇的地方就是used[i - 1] == false也可以,used[i - 1] == true也可以!** 53 | 54 | 我就用输入: [1,1,1] 来举一个例子。 55 | 56 | 树层上去重(used[i - 1] == false),的树形结构如下: 57 | 58 | ![47.全排列II2.png](https://img-blog.csdnimg.cn/20201112172230434.png) 59 | 60 | 树枝上去重(used[i - 1] == true)的树型结构如下: 61 | 62 | ![47.全排列II3](https://img-blog.csdnimg.cn/20201112172327967.png) 63 | 64 | **可以清晰的看到使用(used[i - 1] == false),即树层去重,效率更高!** 65 | 66 | ## 性能分析 67 | 68 | 之前并没有分析各个问题的时间复杂度和空间复杂度,这次来说一说。 69 | 70 | 这块网上的资料鱼龙混杂,一些所谓的经典面试书籍根本不讲回溯算法,算法书籍对这块也避而不谈,感觉就像是算法里模糊的边界。 71 | 72 | **所以这块就说一说我个人理解,对内容持开放态度,集思广益,欢迎大家来讨论!** 73 | 74 | 子集问题分析: 75 | * 时间复杂度:$O(n × 2^n)$,因为每一个元素的状态无外乎取与不取,所以时间复杂度为$O(2^n)$,构造每一组子集都需要填进数组,又有需要$O(n)$,最终时间复杂度:$O(n × 2^n)$。 76 | * 空间复杂度:$O(n)$,递归深度为n,所以系统栈所用空间为$O(n)$,每一层递归所用的空间都是常数级别,注意代码里的result和path都是全局变量,就算是放在参数里,传的也是引用,并不会新申请内存空间,最终空间复杂度为$O(n)$。 77 | 78 | 排列问题分析: 79 | * 时间复杂度:$O(n!)$,这个可以从排列的树形图中很明显发现,每一层节点为n,第二层每一个分支都延伸了n-1个分支,再往下又是n-2个分支,所以一直到叶子节点一共就是 n * n-1 * n-2 * ..... 1 = n!。 80 | * 空间复杂度:$O(n)$,和子集问题同理。 81 | 82 | 组合问题分析: 83 | * 时间复杂度:$O(n × 2^n)$,组合问题其实就是一种子集的问题,所以组合问题最坏的情况,也不会超过子集问题的时间复杂度。 84 | * 空间复杂度:$O(n)$,和子集问题同理。 85 | 86 | **一般说道回溯算法的复杂度,都说是指数级别的时间复杂度,这也算是一个概括吧!** 87 | 88 | ## 总结 89 | 90 | 本周我们对[子集问题进行了去重](https://programmercarl.com/0090.子集II.html),然后介绍了和子集问题非常像的[递增子序列](https://programmercarl.com/0491.递增子序列.html),如果还保持惯性思维,这道题就可以掉坑里。 91 | 92 | 接着介绍了[排列问题!](https://programmercarl.com/0046.全排列.html),以及对[排列问题如何进行去重](https://programmercarl.com/0047.全排列II.html)。 93 | 94 | 最后我补充了子集问题,排列问题和组合问题的性能分析,给大家提供了回溯算法复杂度的分析思路。 95 | 96 | 97 | 98 |
99 | -------------------------------------------------------------------------------- /problems/周总结/20201010二叉树周末总结.md: -------------------------------------------------------------------------------- 1 | 2 | # 本周小结!(二叉树系列三) 3 | 4 | 5 | ## 周一 6 | 7 | 在[二叉树:以为使用了递归,其实还隐藏着回溯](https://programmercarl.com/二叉树中递归带着回溯.html)中,通过leetcode [257.二叉树的所有路径这道题目](https://programmercarl.com/0257.二叉树的所有路径.html),讲解了递归如何隐藏着回溯,一些代码会把回溯的过程都隐藏了起来了,甚至刷过这道题的同学可能都不知道自己用了回溯。 8 | 9 | 文章中第一版代码把每一个细节都展示了输出来了,大家可以清晰的看到回溯的过程。 10 | 11 | 然后给出了第二版优化后的代码,分析了其回溯隐藏在了哪里,如果要把这个回溯扣出来的话,在第二版的基础上应该怎么改。 12 | 13 | 主要需要理解:**回溯隐藏在traversal(cur->left, path + "->", result);中的 path + "->"。 每次函数调用完,path依然是没有加上"->" 的,这就是回溯了。** 14 | 15 | 16 | ## 周二 17 | 18 | 在文章[二叉树:做了这么多题目了,我的左叶子之和是多少?](https://programmercarl.com/0404.左叶子之和.html) 中提供了另一个判断节点属性的思路,平时我们习惯了使用通过节点的左右孩子判断本节点的属性,但发现使用这个思路无法判断左叶子。 19 | 20 | 此时需要相连的三层之间构成的约束条件,也就是要通过节点的父节点以及孩子节点来判断本节点的属性。 21 | 22 | 这道题目可以扩展大家对二叉树的解题思路。 23 | 24 | 25 | ## 周三 26 | 27 | 在[二叉树:我的左下角的值是多少?](https://programmercarl.com/0513.找树左下角的值.html)中的题目如果使用递归的写法还是有点难度的,层次遍历反而很简单。 28 | 29 | 题目其实就是要在树的**最后一行**找到**最左边的值**。 30 | 31 | **如何判断是最后一行呢,其实就是深度最大的叶子节点一定是最后一行。** 32 | 33 | 在这篇文章中,我们使用递归算法实实在在的求了一次深度,然后使用靠左的遍历,保证求得靠左的最大深度,而且又一次使用了回溯。 34 | 35 | 如果对二叉树的高度与深度又有点模糊了,在看这里[二叉树:我平衡么?](https://programmercarl.com/0110.平衡二叉树.html),回忆一下吧。 36 | 37 | [二叉树:我的左下角的值是多少?](https://programmercarl.com/0513.找树左下角的值.html)中把我们之前讲过的内容都过了一遍,此外,还用前序遍历的技巧求得了靠左的最大深度。 38 | 39 | **求二叉树的各种最值,就想应该采用什么样的遍历顺序,确定了遍历循序,其实就和数组求最值一样容易了。** 40 | 41 | 42 | ## 周四 43 | 44 | 在[二叉树:递归函数究竟什么时候需要返回值,什么时候不要返回值?](https://programmercarl.com/0112.路径总和.html)中通过两道题目,彻底说清楚递归函数的返回值问题。 45 | 46 | 一般情况下:**如果需要搜索整棵二叉树,那么递归函数就不要返回值,如果要搜索其中一条符合条件的路径,递归函数就需要返回值,因为遇到符合条件的路径了就要及时返回。** 47 | 48 | 特别是有些时候 递归函数的返回值是bool类型,一些同学会疑惑为啥要加这个,其实就是为了找到一条边立刻返回。 49 | 50 | 其实还有一种就是后序遍历需要根据左右递归的返回值推出中间节点的状态,这种需要有返回值,例如[222.完全二叉树](https://programmercarl.com/0222.完全二叉树的节点个数.html),[110.平衡二叉树](https://programmercarl.com/0110.平衡二叉树.html),这几道我们之前也讲过。 51 | 52 | ## 周五 53 | 54 | 之前都是讲解遍历二叉树,这次该构造二叉树了,在[二叉树:构造二叉树登场!](https://programmercarl.com/0106.从中序与后序遍历序列构造二叉树.html)中,我们通过前序和中序,后序和中序,构造了唯一的一棵二叉树。 55 | 56 | **构造二叉树有三个注意的点:** 57 | 58 | * 分割时候,坚持区间不变量原则,左闭右开,或者左闭又闭。 59 | * 分割的时候,注意后序 或者 前序已经有一个节点作为中间节点了,不能继续使用了。 60 | * 如何使用切割后的后序数组来切合中序数组?利用中序数组大小一定是和后序数组的大小相同这一特点来进行切割。 61 | 62 | 这道题目代码实现并不简单,大家啃下来之后,二叉树的构造应该不是问题了。 63 | 64 | **最后我还给出了为什么前序和后序不能唯一构成一棵二叉树,因为没有中序遍历就无法确定左右部分,也就无法分割。** 65 | 66 | ## 周六 67 | 68 | 知道了如何构造二叉树,那么使用一个套路就可以解决文章[二叉树:构造一棵最大的二叉树](https://programmercarl.com/0654.最大二叉树.html)中的问题。 69 | 70 | **注意类似用数组构造二叉树的题目,每次分隔尽量不要定义新的数组,而是通过下标索引直接在原数组上操作,这样可以节约时间和空间上的开销。** 71 | 72 | 文章中我还给出了递归函数什么时候加if,什么时候不加if,其实就是控制空节点(空指针)是否进入递归,是不同的代码实现方式,都是可以的。 73 | 74 | **一般情况来说:如果让空节点(空指针)进入递归,就不加if,如果不让空节点进入递归,就加if限制一下, 终止条件也会相应的调整。** 75 | 76 | ## 总结 77 | 78 | 本周我们深度讲解了如下知识点: 79 | 80 | 1. [递归中如何隐藏着回溯](https://programmercarl.com/二叉树中递归带着回溯.html) 81 | 2. [如何通过三层关系确定左叶子](https://programmercarl.com/0404.左叶子之和.html) 82 | 3. [如何通过二叉树深度来判断左下角的值](https://programmercarl.com/0513.找树左下角的值.html) 83 | 4. [递归函数究竟什么时候需要返回值,什么时候不要返回值?](https://programmercarl.com/0112.路径总和.html) 84 | 5. [前序和中序,后序和中序构造唯一二叉树](https://programmercarl.com/0106.从中序与后序遍历序列构造二叉树.html) 85 | 6. [使用数组构造某一特性的二叉树](https://programmercarl.com/0654.最大二叉树.html) 86 | 87 | **如果大家一路跟下来,一定收获满满,如果周末不做这个总结,大家可能都不知道自己收获满满,啊哈!** 88 | 89 | 90 |
91 | -------------------------------------------------------------------------------- /problems/周总结/20201224贪心周末总结.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 本周小结!(贪心算法系列四) 4 | 5 | ## 周一 6 | 7 | 在[贪心算法:用最少数量的箭引爆气球](https://programmercarl.com/0452.用最少数量的箭引爆气球.html)中,我们开始讲解了重叠区间问题,用最少的弓箭射爆所有气球,其本质就是找到最大的重叠区间。 8 | 9 | 按照左边界进行排序后,如果气球重叠了,重叠气球中右边边界的最小值 之前的区间一定需要一个弓箭 10 | 11 | 如图: 12 | 13 | ![452.用最少数量的箭引爆气球](https://img-blog.csdnimg.cn/20201123101929791.png) 14 | 15 | 模拟射气球的过程,很多同学真的要去模拟了,实时把气球从数组中移走,这么写的话就复杂了,从前向后遍历重复的只要跳过就可以的。 16 | 17 | ## 周二 18 | 19 | 在[贪心算法:无重叠区间](https://programmercarl.com/0435.无重叠区间.html)中要去掉最少的区间,来让所有区间没有重叠。 20 | 21 | 我来按照右边界排序,从左向右记录非交叉区间的个数。最后用区间总数减去非交叉区间的个数就是需要移除的区间个数了。 22 | 23 | 如图: 24 | 25 | ![435.无重叠区间](https://img-blog.csdnimg.cn/20201221201553618.png) 26 | 27 | 细心的同学就发现了,此题和 [贪心算法:用最少数量的箭引爆气球](https://programmercarl.com/0452.用最少数量的箭引爆气球.html)非常像。 28 | 29 | 弓箭的数量就相当于是非交叉区间的数量,只要把弓箭那道题目代码里射爆气球的判断条件加个等号(认为[0,1][1,2]不是相邻区间),然后用总区间数减去弓箭数量 就是要移除的区间数量了。 30 | 31 | 把[贪心算法:用最少数量的箭引爆气球](https://programmercarl.com/0452.用最少数量的箭引爆气球.html)代码稍做修改,就可以AC本题。 32 | 33 | 修改后的C++代码如下: 34 | ```CPP 35 | class Solution { 36 | public: 37 | // 按照区间左边界从大到小排序 38 | static bool cmp (const vector& a, const vector& b) { 39 | return a[0] < b[0]; 40 | } 41 | int eraseOverlapIntervals(vector>& intervals) { 42 | if (intervals.size() == 0) return 0; 43 | sort(intervals.begin(), intervals.end(), cmp); 44 | 45 | int result = 1; 46 | for (int i = 1; i < intervals.size(); i++) { 47 | if (intervals[i][0] >= intervals[i - 1][1]) { // 需要要把> 改成 >= 就可以了 48 | result++; // 需要一支箭 49 | } 50 | else { 51 | intervals[i][1] = min(intervals[i - 1][1], intervals[i][1]); // 更新重叠气球最小右边界 52 | } 53 | } 54 | return intervals.size() - result; 55 | } 56 | }; 57 | ``` 58 | 59 | ## 周三 60 | 61 | [贪心算法:划分字母区间](https://programmercarl.com/0763.划分字母区间.html)中我们要把这个字符串划分为尽可能多的片段,同一字母最多出现在一个片段中。 62 | 63 | 这道题目leetcode上标的是贪心,其实我不认为是贪心,因为没感受到局部最优和全局最优的关系。 64 | 65 | 但不影响这是一道好题,思路很不错,**通过字符出现最远距离取并集的方法,把出现过的字符都圈到一个区间里**。 66 | 67 | 解题过程分如下两步: 68 | 69 | * 统计每一个字符最后出现的位置 70 | * 从头遍历字符,并更新字符的最远出现下标,如果找到字符最远出现位置下标和当前下标相等了,则找到了分割点 71 | 72 | 如图: 73 | 74 | ![763.划分字母区间](https://img-blog.csdnimg.cn/20201222191924417.png) 75 | 76 | 77 | ## 周四 78 | 79 | [贪心算法:合并区间](https://programmercarl.com/0056.合并区间.html)中要合并所有重叠的区间。 80 | 81 | 相信如果录友们前几天区间问题的题目认真练习了,今天题目就应该算简单一些了。 82 | 83 | 按照左边界排序,排序之后局部最优:每次合并都取最大的右边界,这样就可以合并更多的区间了,整体最优:合并所有重叠的区间。 84 | 85 | 具体操作:按照左边界从小到大排序之后,如果 intervals[i][0] < intervals[i - 1][1] 即intervals[i]左边界 < intervals[i - 1]右边界,则一定有重复,因为intervals[i]的左边界一定是大于等于intervals[i - 1]的左边界。 86 | 87 | 如图: 88 | 89 | ![56.合并区间](https://img-blog.csdnimg.cn/20201223200632791.png) 90 | 91 | 92 | ## 总结 93 | 94 | 本周的主题就是用贪心算法来解决区间问题,经过本周的学习,大家应该对区间的各种合并分割有一定程度的了解了。 95 | 96 | 其实很多区间的合并操作看起来都是常识,其实贪心算法有时候就是常识,哈哈,但也别小看了贪心算法。 97 | 98 | 在[贪心算法:合并区间](https://programmercarl.com/0056.合并区间.html)中就说过,对于贪心算法,很多同学都是:「如果能凭常识直接做出来,就会感觉不到自己用了贪心, 一旦第一直觉想不出来, 可能就一直想不出来了」。 99 | 100 | 所以还是要多看多做多练习! 101 | 102 | **「代码随想录」里总结的都是经典题目,大家跟着练就节省了不少选择题目的时间了**。 103 | 104 | 105 |
106 | -------------------------------------------------------------------------------- /problems/1221.分割平衡字符串.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 |

参与本项目,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!

6 | 7 | # 1221. 分割平衡字符串 8 | 9 | [力扣题目链接](https://leetcode-cn.com/problems/split-a-string-in-balanced-strings/) 10 | 11 | 在一个 平衡字符串 中,'L' 和 'R' 字符的数量是相同的。 12 | 13 | 给你一个平衡字符串 s,请你将它分割成尽可能多的平衡字符串。 14 | 15 | 注意:分割得到的每个字符串都必须是平衡字符串。 16 | 17 | 返回可以通过分割得到的平衡字符串的 最大数量 。 18 | 19 | 20 | 示例 1: 21 | 22 | * 输入:s = "RLRRLLRLRL" 23 | * 输出:4 24 | * 解释:s 可以分割为 "RL"、"RRLL"、"RL"、"RL" ,每个子字符串中都包含相同数量的 'L' 和 'R' 。 25 | 26 | 示例 2: 27 | * 输入:s = "RLLLLRRRLR" 28 | * 输出:3 29 | * 解释:s 可以分割为 "RL"、"LLLRRR"、"LR" ,每个子字符串中都包含相同数量的 'L' 和 'R' 。 30 | 31 | 示例 3: 32 | * 输入:s = "LLLLRRRR" 33 | * 输出:1 34 | * 解释:s 只能保持原样 "LLLLRRRR". 35 | 36 | 示例 4: 37 | * 输入:s = "RLRRRLLRLL" 38 | * 输出:2 39 | * 解释:s 可以分割为 "RL"、"RRRLLRLL" ,每个子字符串中都包含相同数量的 'L' 和 'R' 。 40 | 41 | ## 思路 42 | 43 | 这道题目看起来好像很复杂,其实是非常简单的贪心,关于贪心,我在这里[关于贪心算法,你该了解这些!](https://programmercarl.com/贪心算法理论基础.html)有详细的讲解。 44 | 45 | 从前向后遍历,只要遇到平衡子串,计数就+1,遍历一遍即可。 46 | 47 | 局部最优:从前向后遍历,只要遇到平衡子串 就统计 48 | 49 | 全局最优:统计了最多的平衡子串。 50 | 51 | 局部最优可以推出全局最优,举不出反例,那么就试试贪心。 52 | 53 | 54 | 例如,LRLR 这本身就是平衡子串 , 但要遇到LR就可以分割。 55 | 56 | C++代码如下: 57 | 58 | ```CPP 59 | class Solution { 60 | public: 61 | int balancedStringSplit(string s) { 62 | int result = 0; 63 | int count = 0; 64 | for (int i = 0; i < s.size(); i++) { 65 | if (s[i] == 'R') count++; 66 | else count--; 67 | if (count == 0) result++; 68 | } 69 | return result; 70 | } 71 | }; 72 | ``` 73 | 74 | ## 拓展 75 | 76 | 一些同学可能想,你这个推理不靠谱,都没有数学证明。怎么就能说是合理的呢,怎么就能说明 局部最优可以推出全局最优呢? 77 | 78 | 一般数学证明有如下两种方法: 79 | 80 | * 数学归纳法 81 | * 反证法 82 | 83 | 如果真的去严格数学证明其实不是在我们刷题或者 面试的考察范围内了。 84 | 85 | 所以贪心题目的思考过程是: 如果发现局部最优好像可以推出全局最优,那么就 尝试一下举反例,如果举不出反例,那么就试试贪心。 86 | 87 | 88 | 89 | ## 其他语言版本 90 | 91 | ### Java 92 | 93 | ```java 94 | class Solution { 95 | public int balancedStringSplit(String s) { 96 | int result = 0; 97 | int count = 0; 98 | for (int i = 0; i < s.length(); i++) { 99 | if (s.charAt(i) == 'R') count++; 100 | else count--; 101 | if (count == 0) result++; 102 | } 103 | return result; 104 | } 105 | } 106 | ``` 107 | 108 | ### Python 109 | 110 | ```python 111 | ``` 112 | 113 | ### Go 114 | 115 | ```go 116 | ``` 117 | 118 | ### JavaScript 119 | 120 | ```js 121 | var balancedStringSplit = function(s) { 122 | let res = 0, total = 0;//res为平衡字符串数量 total为当前"R"字符和"L"字符的数量差 123 | for(let c of s){// 遍历字符串每个字符 124 | //因为开始字符数量差就是0,遍历的时候要先改变数量差,否则会影响结果数量 125 | total += c === 'R' ? 1:-1;//遇到"R",total++;遇到"L",total-- 126 | if(total === 0) res++;//只要"R""L"数量一样就可以算是一个平衡字符串 127 | } 128 | return res; 129 | }; 130 | ``` 131 | 132 | 133 | ----------------------- 134 |
135 | -------------------------------------------------------------------------------- /problems/数组理论基础.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 |

参与本项目,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!

6 | 7 | 8 | 9 | ## 数组理论基础 10 | 11 | 数组是非常基础的数据结构,在面试中,考察数组的题目一般在思维上都不难,主要是考察对代码的掌控能力 12 | 13 | 也就是说,想法很简单,但实现起来 可能就不是那么回事了。 14 | 15 | 首先要知道数组在内存中的存储方式,这样才能真正理解数组相关的面试题 16 | 17 | **数组是存放在连续内存空间上的相同类型数据的集合。** 18 | 19 | 数组可以方便的通过下标索引的方式获取到下标下对应的数据。 20 | 21 | 举一个字符数组的例子,如图所示: 22 | 23 | ![算法通关数组](https://code-thinking.cdn.bcebos.com/pics/%E7%AE%97%E6%B3%95%E9%80%9A%E5%85%B3%E6%95%B0%E7%BB%84.png) 24 | 25 | 26 | 27 | 需要两点注意的是 28 | 29 | * **数组下标都是从0开始的。** 30 | * **数组内存空间的地址是连续的** 31 | 32 | 正是**因为数组的在内存空间的地址是连续的,所以我们在删除或者增添元素的时候,就难免要移动其他元素的地址。** 33 | 34 | 例如删除下标为3的元素,需要对下标为3的元素后面的所有元素都要做移动操作,如图所示: 35 | 36 | ![算法通关数组1](https://code-thinking.cdn.bcebos.com/pics/%E7%AE%97%E6%B3%95%E9%80%9A%E5%85%B3%E6%95%B0%E7%BB%841.png) 37 | 38 | 39 | 而且大家如果使用C++的话,要注意vector 和 array的区别,vector的底层实现是array,严格来讲vector是容器,不是数组。 40 | 41 | **数组的元素是不能删的,只能覆盖。** 42 | 43 | 那么二维数组直接上图,大家应该就知道怎么回事了 44 | 45 | ![算法通关数组2](https://code-thinking.cdn.bcebos.com/pics/%E7%AE%97%E6%B3%95%E9%80%9A%E5%85%B3%E6%95%B0%E7%BB%842.png) 46 | 47 | 48 | **那么二维数组在内存的空间地址是连续的么?** 49 | 50 | 不同编程语言的内存管理是不一样的,以C++为例,在C++中二维数组是连续分布的。 51 | 52 | 我们来做一个实验,C++测试代码如下: 53 | 54 | ```CPP 55 | void test_arr() { 56 | int array[2][3] = { 57 | {0, 1, 2}, 58 | {3, 4, 5} 59 | }; 60 | cout << &array[0][0] << " " << &array[0][1] << " " << &array[0][2] << endl; 61 | cout << &array[1][0] << " " << &array[1][1] << " " << &array[1][2] << endl; 62 | } 63 | 64 | int main() { 65 | test_arr(); 66 | } 67 | 68 | ``` 69 | 70 | 测试地址为 71 | 72 | ``` 73 | 0x7ffee4065820 0x7ffee4065824 0x7ffee4065828 74 | 0x7ffee406582c 0x7ffee4065830 0x7ffee4065834 75 | ``` 76 | 77 | 注意地址为16进制,可以看出二维数组地址是连续一条线的。 78 | 79 | 一些录友可能看不懂内存地址,我就简单介绍一下, 0x7ffee4065820 与 0x7ffee4065824 差了一个4,就是4个字节,因为这是一个int型的数组,所以两个相邻数组元素地址差4个字节。 80 | 81 | 0x7ffee4065828 与 0x7ffee406582c 也是差了4个字节,在16进制里8 + 4 = c,c就是12。 82 | 83 | 如图: 84 | 85 | ![数组内存](https://img-blog.csdnimg.cn/20210310150641186.png) 86 | 87 | **所以可以看出在C++中二维数组在地址空间上是连续的**。 88 | 89 | 像Java是没有指针的,同时也不对程序员暴露其元素的地址,寻址操作完全交给虚拟机。 90 | 91 | 所以看不到每个元素的地址情况,这里我以Java为例,也做一个实验。 92 | 93 | ```Java 94 | public static void test_arr() { 95 | int[][] arr = {{1, 2, 3}, {3, 4, 5}, {6, 7, 8}, {9,9,9}}; 96 | System.out.println(arr[0]); 97 | System.out.println(arr[1]); 98 | System.out.println(arr[2]); 99 | System.out.println(arr[3]); 100 | } 101 | ``` 102 | 输出的地址为: 103 | 104 | ``` 105 | [I@7852e922 106 | [I@4e25154f 107 | [I@70dea4e 108 | [I@5c647e05 109 | ``` 110 | 111 | 这里的数值也是16进制,这不是真正的地址,而是经过处理过后的数值了,我们也可以看出,二维数组的每一行头结点的地址是没有规则的,更谈不上连续。 112 | 113 | 所以Java的二维数组可能是如下排列的方式: 114 | 115 | ![算法通关数组3](https://img-blog.csdnimg.cn/20201214111631844.png) 116 | 117 | 这里面试中数组相关的理论知识就介绍完了。 118 | 119 | 120 | 121 | ----------------------- 122 |
123 | -------------------------------------------------------------------------------- /problems/周总结/20201126贪心周末总结.md: -------------------------------------------------------------------------------- 1 | 2 | # 本周小结!(贪心算法系列一) 3 | 4 | ## 周一 5 | 6 | 本周正式开始了贪心算法,在[关于贪心算法,你该了解这些!](https://programmercarl.com/贪心算法理论基础.html)中,我们介绍了什么是贪心以及贪心的套路。 7 | 8 | **贪心的本质是选择每一阶段的局部最优,从而达到全局最优。** 9 | 10 | 有没有啥套路呢? 11 | 12 | **不好意思,贪心没套路,就刷题而言,如果感觉好像局部最优可以推出全局最优,然后想不到反例,那就试一试贪心吧!** 13 | 14 | 而严格的数据证明一般有如下两种: 15 | 16 | * 数学归纳法 17 | * 反证法 18 | 19 | 数学就不在讲解范围内了,感兴趣的同学可以自己去查一查资料。 20 | 21 | 正式因为贪心算法有时候会感觉这是常识,本就应该这么做! 所以大家经常看到网上有人说这是一道贪心题目,有人是这不是。 22 | 23 | 这里说一下我的依据:**如果找到局部最优,然后推出整体最优,那么就是贪心**,大家可以参考哈。 24 | 25 | ## 周二 26 | 27 | 28 | 在[贪心算法:分发饼干](https://programmercarl.com/0455.分发饼干.html)中讲解了贪心算法的第一道题目。 29 | 30 | 这道题目很明显能看出来是用贪心,也是入门好题。 31 | 32 | 我在文中给出**局部最优:大饼干喂给胃口大的,充分利用饼干尺寸喂饱一个,全局最优:喂饱尽可能多的小孩**。 33 | 34 | 很多录友都是用小饼干优先先喂饱小胃口的。 35 | 36 | 后来我想一想,虽然结果是一样的,但是大家的这个思考方式更好一些。 37 | 38 | **因为用小饼干优先喂饱小胃口的 这样可以尽量保证最后省下来的是大饼干(虽然题目没有这个要求)!** 39 | 40 | 所有还是小饼干优先先喂饱小胃口更好一些,也比较直观。 41 | 42 | 一些录友不清楚[贪心算法:分发饼干](https://programmercarl.com/0455.分发饼干.html)中时间复杂度是怎么来的? 43 | 44 | 就是快排$O(n\log n)$,遍历$O(n)$,加一起就是还是$O(n\log n)$。 45 | 46 | ## 周三 47 | 48 | 接下来就要上一点难度了,要不然大家会误以为贪心算法就是常识判断一下就行了。 49 | 50 | 在[贪心算法:摆动序列](https://programmercarl.com/0376.摆动序列.html)中,需要计算最长摇摆序列。 51 | 52 | 其实就是让序列有尽可能多的局部峰值。 53 | 54 | 局部最优:删除单调坡度上的节点(不包括单调坡度两端的节点),那么这个坡度就可以有两个局部峰值。 55 | 56 | 整体最优:整个序列有最多的局部峰值,从而达到最长摆动序列。 57 | 58 | 在计算峰值的时候,还是有一些代码技巧的,例如序列两端的峰值如何处理。 59 | 60 | 这些技巧,其实还是要多看多用才会掌握。 61 | 62 | 63 | ## 周四 64 | 65 | 在[贪心算法:最大子序和](https://programmercarl.com/0053.最大子序和.html)中,详细讲解了用贪心的方式来求最大子序列和,其实这道题目是一道动态规划的题目。 66 | 67 | **贪心的思路为局部最优:当前“连续和”为负数的时候立刻放弃,从下一个元素重新计算“连续和”,因为负数加上下一个元素 “连续和”只会越来越小。从而推出全局最优:选取最大“连续和”** 68 | 69 | 代码很简单,但是思路却比较难。还需要反复琢磨。 70 | 71 | 针对[贪心算法:最大子序和](https://programmercarl.com/0053.最大子序和.html)文章中给出的贪心代码如下; 72 | ``` 73 | class Solution { 74 | public: 75 | int maxSubArray(vector& nums) { 76 | int result = INT32_MIN; 77 | int count = 0; 78 | for (int i = 0; i < nums.size(); i++) { 79 | count += nums[i]; 80 | if (count > result) { // 取区间累计的最大值(相当于不断确定最大子序终止位置) 81 | result = count; 82 | } 83 | if (count <= 0) count = 0; // 相当于重置最大子序起始位置,因为遇到负数一定是拉低总和 84 | } 85 | return result; 86 | } 87 | }; 88 | ``` 89 | 不少同学都来问,如果数组全是负数这个代码就有问题了,如果数组里有int最小值这个代码就有问题了。 90 | 91 | 大家不要脑洞模拟哈,可以亲自构造一些测试数据试一试,就发现其实没有问题。 92 | 93 | 数组都为负数,result记录的就是最小的负数,如果数组里有int最小值,那么最终result就是int最小值。 94 | 95 | 96 | ## 总结 97 | 98 | 本周我们讲解了[贪心算法的理论基础](https://programmercarl.com/贪心算法理论基础.html),了解了贪心本质:局部最优推出全局最优。 99 | 100 | 然后讲解了第一道题目[分发饼干](https://programmercarl.com/0455.分发饼干.html),还是比较基础的,可能会给大家一种贪心算法比较简单的错觉,因为贪心有时候接近于常识。 101 | 102 | 其实我还准备一些简单的贪心题目,甚至网上很多都质疑这些题目是不是贪心算法。这些题目我没有立刻发出来,因为真的会让大家感觉贪心过于简单,而忽略了贪心的本质:局部最优和全局最优两个关键点。 103 | 104 | **所以我在贪心系列难度会有所交替,难的题目在于拓展思路,简单的题目在于分析清楚其贪心的本质,后续我还会发一些简单的题目来做贪心的分析。** 105 | 106 | 在[摆动序列](https://programmercarl.com/0376.摆动序列.html)中大家就初步感受到贪心没那么简单了。 107 | 108 | 本周最后是[最大子序和](https://programmercarl.com/0053.最大子序和.html),这道题目要用贪心的方式做出来,就比较有难度,都知道负数加上正数之后会变小,但是这道题目依然会让很多人搞混淆,其关键在于:**不能让“连续和”为负数的时候加上下一个元素,而不是 不让“连续和”加上一个负数**。这块真的需要仔细体会! 109 | 110 | 111 | 112 | 113 | 114 | 115 |
116 | -------------------------------------------------------------------------------- /problems/前序/什么是核心代码模式,什么又是ACM模式?.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 | 6 |

7 |

欢迎大家参与本项目,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!

8 | 9 | 10 | 现在很多企业都在牛客上进行面试,**很多录友和我反馈说搞不懂牛客上输入代码的ACM模式**。 11 | 12 | 什么是ACM输入模式呢? 就是自己构造输入数据格式,把要需要处理的容器填充好,OJ不会给你任何代码,包括include哪些函数都要自己写,最后也要自己控制返回数据的格式。 13 | 14 | 而力扣上是核心代码模式,就是把要处理的数据都已经放入容器里,可以直接写逻辑,例如这样: 15 | 16 | ```CPP 17 | class Solution { 18 | public: 19 | int minimumTotal(vector>& triangle) { 20 | 21 | } 22 | }; 23 | ``` 24 | 25 | **如果大家从一开始学习算法就一直在力扣上的话,突然切到牛客网上的ACM模式会很不适应**。 26 | 27 | 因为我上学的时候就搞ACM,在POJ(北大的在线判题系统)和ZOJ(浙大的在线判题系统)上刷过6、7百道题目了,对这种ACM模式就很熟悉。 28 | 29 | 接下来我给大家讲一下ACM模式应该如何写。 30 | 31 | 这里我拿牛客上 腾讯2020校园招聘-后台 的面试题目来举一个例子,本题我不讲解题思路,只是拿本题为例讲解ACM输入输出格式。 32 | 33 | 题目描述: 34 | 35 | 由于业绩优秀,公司给小Q放了 n 天的假,身为工作狂的小Q打算在在假期中工作、锻炼或者休息。他有个奇怪的习惯:不会连续两天工作或锻炼。只有当公司营业时,小Q才能去工作,只有当健身房营业时,小Q才能去健身,小Q一天只能干一件事。给出假期中公司,健身房的营业情况,求小Q最少需要休息几天。 36 | 37 | 输入描述: 38 | 第一行一个整数 表示放假天数 39 | 第二行 n 个数 每个数为0或1,第 i 个数表示公司在第 i 天是否营业 40 | 第三行 n 个数 每个数为0或1,第 i 个数表示健身房在第 i 天是否营业 41 | (1为营业 0为不营业) 42 | 43 | 输出描述: 44 | 一个整数,表示小Q休息的最少天数 45 | 46 | 示例一: 47 | 输入: 48 | 4 49 | 1 1 0 0 50 | 0 1 1 0 51 | 52 | 输出: 53 | 2 54 | 55 | 56 | 这道题如果要是力扣上的核心代码模式,OJ应该直接给出如下代码: 57 | 58 | ```CPP 59 | class Solution { 60 | public: 61 | int getDays(vector& work, vector& gym) { 62 | // 处理逻辑 63 | } 64 | }; 65 | ``` 66 | 67 | 以上代码中我们直接写核心逻辑就行了,work数组,gym数组都是填好的,直接拿来用就行,处理完之后 return 结果就完事了。 68 | 69 | 那么看看ACM模式我们要怎么写呢。 70 | 71 | ACM模式要求写出来的代码是直接可以本地运行的,所以我们需要自己写include哪些库函数,构造输入用例,构造输出用例。 72 | 73 | 拿本题来说,为了让代码可以运行,需要include这些库函数: 74 | 75 | ```CPP 76 | #include 77 | #include 78 | using namespace std; 79 | ``` 80 | 81 | 82 | 然后开始写主函数,来处理输入用例了,示例一 是一个完整的测试用例,一般我们测了一个用例还要测第二个用例,所以用:while(cin>>n) 来输入数据。 83 | 84 | 这里输入的n就是天数,得到天数之后,就可以来构造work数组和gym数组了。 85 | 86 | 此时就已经完成了输入用例构建,然后就是处理逻辑了,最后返回结果。 87 | 88 | 完整代码如下: 89 | 90 | ```CPP 91 | #include 92 | #include 93 | using namespace std; 94 | int main() { 95 | int n; 96 | while (cin >> n) { 97 | vector gym(n); 98 | vector work(n); 99 | for (int i = 0; i < n; i++) cin >> work[i]; 100 | for (int i = 0; i < n; i++) cin >> gym[i]; 101 | int result = 0; 102 | 103 | // 处理逻辑 104 | 105 | cout << result << endl; 106 | } 107 | return 0; 108 | } 109 | ``` 110 | 111 | 可以看出ACM模式要比核心代码模式多写不少代码,相对来说ACM模式更锻炼代码能力,而核心代码模式是把侧重点完全放在算法逻辑上。 112 | 113 | **国内企业现在很多都用牛客来进行面试,所以这种ACM模式大家还有必要熟悉一下**,以免面试的时候因为输入输出搞不懂而错失offer。 114 | 115 | 如果大家有精力的话,也可以去POJ上去刷刷题,POJ是ACM选手首选OJ,输入模式也是ACM模式。 116 | 117 | 118 | 119 | 120 | 121 | ----------------------- 122 |
123 | -------------------------------------------------------------------------------- /problems/前序/上海互联网公司总结.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 | 6 |

7 |

欢迎大家参与本项目,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!

8 | 9 | 10 | # 上海互联网公司总结 11 | 12 | **个人总结难免有所疏忽,欢迎大家补充,公司好坏没有排名哈!** 13 | 14 | ## 一线互联网 15 | 16 | * 百度(上海) 17 | * 阿里(上海) 18 | * 腾讯(上海) 19 | * 字节跳动(上海) 20 | * 蚂蚁金服(上海) 21 | 22 | ## 外企IT/互联网/硬件 23 | 24 | * 互联网 25 | * Google(上海) 26 | * 微软(上海) 27 | * LeetCode/力扣(上海) 28 | * unity(上海)游戏引擎 29 | * SAP(上海)主要产品是ERP 30 | * PayPal(上海)在线支付鼻祖 31 | * eBay(上海)电子商务公司 32 | * 偏硬件 33 | * IBM(上海) 34 | * Tesla(上海)特斯拉 35 | * Cisco(上海)思科 36 | * Intel(上海) 37 | * AMD(上海)半导体产品领域 38 | * EMC(上海)易安信是美国信息存储资讯科技公司 39 | * NVIDIA(上海)英伟达是GPU(图形处理器)的发明者,人工智能计算的引领者 40 | 41 | ## 二线互联网 42 | 43 | * 拼多多(总部) 44 | * 饿了么(总部)阿里旗下。 45 | * 哈啰出行(总部)阿里旗下 46 | * 盒马(总部)阿里旗下 47 | * 哔哩哔哩(总部) 48 | * 阅文集团(总部)腾讯旗下 49 | * 爱奇艺(上海)百度旗下 50 | * 携程(总部) 51 | * 京东(上海) 52 | * 网易(上海) 53 | * 美团点评(上海) 54 | * 唯品会(上海) 55 | 56 | ## 硬件巨头 (有软件/互联网业务) 57 | 58 | 华为(上海) 59 | 60 | ## 三线互联网 61 | 62 | * PPTV(总部) 63 | * 微盟(总部)企业云端商业及营销解决方案提供商 64 | * 喜马拉雅(总部) 65 | * 陆金所(总部)全球领先的线上财富管理平台 66 | * 口碑(上海)阿里旗下。 67 | * 三七互娱(上海) 68 | * 趣头条(总部) 69 | * 巨人网络(总部)游戏公司 70 | * 盛大网络(总部)游戏公司 71 | * UCloud(总部)云服务提供商 72 | * 达达集团(总部)本地即时零售与配送平台 73 | * 众安保险(总部)在线财产保险 74 | * 触宝(总部)触宝输入法等多款APP 75 | * 平安系列 76 | 77 | ## 明星创业公司 78 | 79 | * 小红书(总部) 80 | * 叮咚买菜(总部) 81 | * 蔚来汽车(总部) 82 | * 七牛云(总部) 83 | * 得物App(总部)品潮流尖货装备交易、球鞋潮品鉴别查验、互动潮流社区 84 | * 收钱吧(总部)开创了中国移动支付市场“一站式收款” 85 | * 蜻蜓FM(总部)音频内容聚合平台 86 | * 流利说(总部)在线教育 87 | * Soul(总部)社交软件 88 | * 美味不用等(总部)智慧餐饮服务商 89 | * 微鲸科技(总部)专注于智能家居领域 90 | * 途虎养车(总部) 91 | * 米哈游(总部)游戏公司 92 | * 莉莉丝游戏(总部)游戏公司 93 | * 樊登读书(总部)在线教育 94 | 95 | ## AI独角兽公司 96 | 97 | * 依图科技(总部)和旷视,商汤对标,都是做安防视觉 98 | * 深兰科技(总部)致力于人工智能基础研究和应用开发 99 | 100 | ## 其他行业,涉及互联网 101 | * 花旗、摩根大通等一些列金融巨头 102 | * 百姓网 103 | * 找钢网 104 | * 安居客 105 | * 前程无忧 106 | * 东方财富 107 | * 三大电信运营商:中国移动、中国电信、中国联通 108 | * 沪江英语 109 | * 各大银行 110 | 111 | 通知:很多同学感觉自己基础还比较薄弱,想循序渐进的从头学一遍数据结构与算法,那你来对地方了。在公众号左下角「算法汇总」里已经按照各个系列难易程度排好顺序了,大家跟着文章顺序打卡学习就可以了,留言区有很多录友都在从头打卡!「算法汇总」会持续更新,大家快去看看吧! 112 | 113 | ## 总结 114 | 115 | 大家如果看了[北京有这些互联网公司,你都知道么?](https://programmercarl.com/前序/北京互联网公司总结.html)和[深圳原来有这么多互联网公司,你都知道么?](https://programmercarl.com/前序/深圳互联网公司总结.html)就可以看出中国互联网氛围最浓的当然是北京,其次就是上海! 116 | 117 | 很多人说深圳才是第二,上海没有产生BAT之类的企业。 118 | 119 | **那么来看看上海在垂直领域上是如何独领风骚的,视频领域B站,电商领域拼多多小红书,生活周边有饿了么,大众点评(现与美团合并),互联网金融有蚂蚁金服和陆金所,出行领域有行业老大携程,而且BAT在上海都有部门还是很大的团队,再加上上海众多的外企,以及金融公司(有互联网业务)**。 120 | 121 | 此时就能感受出来,上海的互联网氛围要比深圳强很多! 122 | 123 | 好了,希望这份list可以帮助到想在上海发展的录友们。 124 | 125 | 相对于北京和上海,深圳互联网公司断层很明显,腾讯一家独大,二线三线垂直行业的公司很少,所以说深圳腾讯的员工流动性相对是较低的,因为基本没得选。 126 | 127 | 128 | 129 | 130 | 131 | 132 | ----------------------- 133 |
134 | -------------------------------------------------------------------------------- /problems/周总结/20210128动规周末总结.md: -------------------------------------------------------------------------------- 1 | # 本周小结!(动态规划系列四) 2 | 3 | ## 周一 4 | 5 | [动态规划:目标和!](https://programmercarl.com/0494.目标和.html)要求在数列之间加入+ 或者 -,使其和为S。 6 | 7 | 所有数的总和为sum,假设加法的总和为x,那么可以推出x = (S + sum) / 2。 8 | 9 | S 和 sum都是固定的,那此时问题就转化为01背包问题(数列中的数只能使用一次): 给你一些物品(数字),装满背包(就是x)有几种方法。 10 | 11 | 1. 确定dp数组以及下标的含义 12 | 13 | **dp[j] 表示:填满j(包括j)这么大容积的包,有dp[j]种方法** 14 | 15 | 2. 确定递推公式 16 | 17 | dp[j] += dp[j - nums[i]] 18 | 19 | **注意:求装满背包有几种方法类似的题目,递推公式基本都是这样的**。 20 | 21 | 3. dp数组如何初始化 22 | 23 | dp[0] 初始化为1 ,dp[j]其他下标对应的数值应该初始化为0。 24 | 25 | 4. 确定遍历顺序 26 | 27 | 01背包问题一维dp的遍历,nums放在外循环,target在内循环,且内循环倒序。 28 | 29 | 30 | 5. 举例推导dp数组 31 | 32 | 输入:nums: [1, 1, 1, 1, 1], S: 3 33 | 34 | bagSize = (S + sum) / 2 = (3 + 5) / 2 = 4 35 | 36 | dp数组状态变化如下: 37 | 38 | ![494.目标和](https://img-blog.csdnimg.cn/20210125120743274.jpg) 39 | 40 | ## 周二 41 | 42 | 这道题目[动态规划:一和零!](https://programmercarl.com/0474.一和零.html)算有点难度。 43 | 44 | **不少同学都以为是多重背包,其实这是一道标准的01背包**。 45 | 46 | 这不过这个背包有两个维度,一个是m 一个是n,而不同长度的字符串就是不同大小的待装物品。 47 | 48 | **所以这是一个二维01背包!** 49 | 50 | 1. 确定dp数组(dp table)以及下标的含义 51 | 52 | **dp[i][j]:最多有i个0和j个1的strs的最大子集的大小为dp[i][j]。** 53 | 54 | 55 | 2. 确定递推公式 56 | 57 | dp[i][j] = max(dp[i][j], dp[i - zeroNum][j - oneNum] + 1); 58 | 59 | 字符串集合中的一个字符串0的数量为zeroNum,1的数量为oneNum。 60 | 61 | 3. dp数组如何初始化 62 | 63 | 因为物品价值不会是负数,初始为0,保证递推的时候dp[i][j]不会被初始值覆盖。 64 | 65 | 4. 确定遍历顺序 66 | 67 | 01背包一定是外层for循环遍历物品,内层for循环遍历背包容量且从后向前遍历! 68 | 69 | 5. 举例推导dp数组 70 | 71 | 以输入:["10","0001","111001","1","0"],m = 3,n = 3为例 72 | 73 | 最后dp数组的状态如下所示: 74 | 75 | ![474.一和零](https://img-blog.csdnimg.cn/20210120111201512.jpg) 76 | 77 | ## 周三 78 | 79 | 此时01背包我们就讲完了,正式开始完全背包。 80 | 81 | 在[动态规划:关于完全背包,你该了解这些!](https://programmercarl.com/背包问题理论基础完全背包.html)中我们讲解了完全背包的理论基础。 82 | 83 | 其实完全背包和01背包区别就是完全背包的物品是无限数量。 84 | 85 | 递推公式也是一样的,但难点在于遍历顺序上! 86 | 87 | 完全背包的物品是可以添加多次的,所以遍历背包容量要从小到大去遍历,即: 88 | 89 | ```CPP 90 | // 先遍历物品,再遍历背包 91 | for(int i = 0; i < weight.size(); i++) { // 遍历物品 92 | for(int j = weight[i]; j < bagWeight ; j++) { // 遍历背包容量 93 | dp[j] = max(dp[j], dp[j - weight[i]] + value[i]); 94 | 95 | } 96 | } 97 | ``` 98 | 99 | 基本网上题的题解介绍到这里就到此为止了。 100 | 101 | **那么为什么要先遍历物品,在遍历背包呢?** (灵魂拷问) 102 | 103 | 其实对于纯完全背包,先遍历物品,再遍历背包 与 先遍历背包,再遍历物品都是可以的。我在文中[动态规划:关于完全背包,你该了解这些!](https://programmercarl.com/背包问题理论基础完全背包.html)也给出了详细的解释。 104 | 105 | 这个细节是很多同学忽略掉的点,其实也不算细节了,**相信不少同学在写背包的时候,两层for循环的先后循序搞不清楚,靠感觉来的**。 106 | 107 | 所以理解究竟是先遍历啥,后遍历啥非常重要,这也体现出遍历顺序的重要性! 108 | 109 | 在文中,我也强调了是对纯完全背包,两个for循环先后循序无所谓,那么题目稍有变化,可就有所谓了。 110 | 111 | ## 周四 112 | 113 | 在[动态规划:给你一些零钱,你要怎么凑?](https://programmercarl.com/0518.零钱兑换II.html)中就是给你一堆零钱(零钱个数无限),为凑成amount的组合数有几种。 114 | 115 | **注意这里组合数和排列数的区别!** 116 | 117 | 看到无限零钱个数就知道是完全背包, 118 | 119 | 但本题不是纯完全背包了(求是否能装满背包),而是求装满背包有几种方法。 120 | 121 | 这里在遍历顺序上可就有说法了。 122 | 123 | * 如果求组合数就是外层for循环遍历物品,内层for遍历背包。 124 | * 如果求排列数就是外层for遍历背包,内层for循环遍历物品。 125 | 126 | 这里同学们需要理解一波,我在文中也给出了详细的解释,下周我们将介绍求排列数的完全背包题目来加深对这个遍历顺序的理解。 127 | 128 | 129 | ## 总结 130 | 131 | 相信通过本周的学习,大家已经初步感受到遍历顺序的重要性! 132 | 133 | 很多对动规理解不深入的同学都会感觉:动规嘛,就是把递推公式推出来其他都easy了。 134 | 135 | 其实这是一种错觉,或者说对动规理解的不够深入! 136 | 137 | 我在动规专题开篇介绍[关于动态规划,你该了解这些!](https://programmercarl.com/动态规划理论基础.html)中就强调了 **递推公式仅仅是 动规五部曲里的一小部分, dp数组的定义、初始化、遍历顺序,哪一点没有搞透的话,即使知道递推公式,遇到稍稍难一点的动规题目立刻会感觉写不出来了**。 138 | 139 | 此时相信大家对动规五部曲也有更深的理解了,同样也验证了Carl之前讲过的:**简单题是用来学习方法论的,而遇到难题才体现出方法论的重要性!** 140 | 141 | 142 |
143 | -------------------------------------------------------------------------------- /problems/双指针总结.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 |

参与本项目,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!

6 | 7 | > 又是一波总结 8 | 9 | 相信大家已经对双指针法很熟悉了,但是双指针法并不隶属于某一种数据结构,我们在讲解数组,链表,字符串都用到了双指针法,所有有必要针对双指针法做一个总结。 10 | 11 | # 数组篇 12 | 13 | 在[数组:就移除个元素很难么?](https://programmercarl.com/0027.移除元素.html)中,原地移除数组上的元素,我们说到了数组上的元素,不能真正的删除,只能覆盖。 14 | 15 | 一些同学可能会写出如下代码(伪代码): 16 | 17 | ``` 18 | for (int i = 0; i < array.size(); i++) { 19 | if (array[i] == target) { 20 | array.erase(i); 21 | } 22 | } 23 | ``` 24 | 25 | 这个代码看上去好像是$O(n)$的时间复杂度,其实是$O(n^2)$的时间复杂度,因为erase操作也是$O(n)$的操作。 26 | 27 | 所以此时使用双指针法才展现出效率的优势:**通过两个指针在一个for循环下完成两个for循环的工作。** 28 | 29 | # 字符串篇 30 | 31 | 在[字符串:这道题目,使用库函数一行代码搞定](https://programmercarl.com/0344.反转字符串.html)中讲解了反转字符串,注意这里强调要原地反转,要不然就失去了题目的意义。 32 | 33 | 使用双指针法,**定义两个指针(也可以说是索引下标),一个从字符串前面,一个从字符串后面,两个指针同时向中间移动,并交换元素。**,时间复杂度是$O(n)$。 34 | 35 | 在[替换空格](https://programmercarl.com/剑指Offer05.替换空格.html) 中介绍使用双指针填充字符串的方法,如果想把这道题目做到极致,就不要只用额外的辅助空间了! 36 | 37 | 思路就是**首先扩充数组到每个空格替换成"%20"之后的大小。然后双指针从后向前替换空格。** 38 | 39 | 有同学问了,为什么要从后向前填充,从前向后填充不行么? 40 | 41 | 从前向后填充就是$O(n^2)$的算法了,因为每次添加元素都要将添加元素之后的所有元素向后移动。 42 | 43 | **其实很多数组(字符串)填充类的问题,都可以先预先给数组扩容带填充后的大小,然后在从后向前进行操作。** 44 | 45 | 那么在[字符串:花式反转还不够!](https://programmercarl.com/0151.翻转字符串里的单词.html)中,我们使用双指针法,用$O(n)$的时间复杂度完成字符串删除类的操作,因为题目要产出冗余空格。 46 | 47 | **在删除冗余空格的过程中,如果不注意代码效率,很容易写成了$O(n^2)$的时间复杂度。其实使用双指针法$O(n)$就可以搞定。** 48 | 49 | **主要还是大家用erase用的比较随意,一定要注意for循环下用erase的情况,一般可以用双指针写效率更高!** 50 | 51 | # 链表篇 52 | 53 | 翻转链表是现场面试,白纸写代码的好题,考察了候选者对链表以及指针的熟悉程度,而且代码也不长,适合在白纸上写。 54 | 55 | 在[链表:听说过两天反转链表又写不出来了?](https://programmercarl.com/0206.翻转链表.html)中,讲如何使用双指针法来翻转链表,**只需要改变链表的next指针的指向,直接将链表反转 ,而不用重新定义一个新的链表。** 56 | 57 | 思路还是很简单的,代码也不长,但是想在白纸上一次性写出bugfree的代码,并不是容易的事情。 58 | 59 | 在链表中求环,应该是双指针在链表里最经典的应用,在[链表:环找到了,那入口呢?](https://programmercarl.com/0142.环形链表II.html)中讲解了如何通过双指针判断是否有环,而且还要找到环的入口。 60 | 61 | **使用快慢指针(双指针法),分别定义 fast 和 slow指针,从头结点出发,fast指针每次移动两个节点,slow指针每次移动一个节点,如果 fast 和 slow指针在途中相遇 ,说明这个链表有环。** 62 | 63 | 那么找到环的入口,其实需要点简单的数学推理,我在文章中把找环的入口清清楚楚的推理的一遍,如果对找环入口不够清楚的同学建议自己看一看[链表:环找到了,那入口呢?](https://programmercarl.com/0142.环形链表II.html)。 64 | 65 | # N数之和篇 66 | 67 | 在[哈希表:解决了两数之和,那么能解决三数之和么?](https://programmercarl.com/0015.三数之和.html)中,讲到使用哈希法可以解决1.两数之和的问题 68 | 69 | 其实使用双指针也可以解决1.两数之和的问题,只不过1.两数之和求的是两个元素的下标,没法用双指针,如果改成求具体两个元素的数值就可以了,大家可以尝试用双指针做一个leetcode上两数之和的题目,就可以体会到我说的意思了。 70 | 71 | 使用了哈希法解决了两数之和,但是哈希法并不使用于三数之和! 72 | 73 | 使用哈希法的过程中要把符合条件的三元组放进vector中,然后在去去重,这样是非常费时的,很容易超时,也是三数之和通过率如此之低的根源所在。 74 | 75 | 去重的过程不好处理,有很多小细节,如果在面试中很难想到位。 76 | 77 | 时间复杂度可以做到$O(n^2)$,但还是比较费时的,因为不好做剪枝操作。 78 | 79 | 所以这道题目使用双指针法才是最为合适的,用双指针做这道题目才能就能真正体会到,**通过前后两个指针不算向中间逼近,在一个for循环下完成两个for循环的工作。** 80 | 81 | 只用双指针法时间复杂度为$O(n^2)$,但比哈希法的$O(n^2)$效率高得多,哈希法在使用两层for循环的时候,能做的剪枝操作很有限。 82 | 83 | 在[双指针法:一样的道理,能解决四数之和](https://programmercarl.com/0018.四数之和.html)中,讲到了四数之和,其实思路是一样的,**在三数之和的基础上再套一层for循环,依然是使用双指针法。** 84 | 85 | 对于三数之和使用双指针法就是将原本暴力$O(n^3)$的解法,降为$O(n^2)$的解法,四数之和的双指针解法就是将原本暴力$O(n^4)$的解法,降为$O(n^3)$的解法。 86 | 87 | 同样的道理,五数之和,n数之和都是在这个基础上累加。 88 | 89 | 90 | # 总结 91 | 92 | 本文中一共介绍了leetcode上九道使用双指针解决问题的经典题目,除了链表一些题目一定要使用双指针,其他题目都是使用双指针来提高效率,一般是将$O(n^2)$的时间复杂度,降为$O(n)$。 93 | 94 | 建议大家可以把文中涉及到的题目在好好做一做,琢磨琢磨,基本对双指针法就不在话下了。 95 | 96 | 97 | ----------------------- 98 |
99 | -------------------------------------------------------------------------------- /problems/前序/程序员写文档工具.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 | 6 |

7 |

欢迎大家参与本项目,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!

8 | 9 | 10 | 11 | 12 | # 程序员应该用什么用具来写文档? 13 | 14 | Carl平时写东西,都是统一使用markdown,包括题解啊,笔记啊,所以这里给大家安利一波markdown对程序员的重要性! 15 | 16 | 程序员为什么要学习markdown呢? 17 | 18 | **一个让你难以拒绝的理由:markdown可以让你养成了记录的习惯**。 19 | 20 | 自从使用了markdown之后,就喜欢了写文档无法自拔,包括记录工作日志,记录周会,记录季度计划,记录学习目标,写各种设计文档。 21 | 22 | 有一种写代码一样的舒爽,markdown 和vim 一起用,简直绝配! 23 | 24 | 那来说一说markdown的好处。 25 | 26 | ## 为什么需要markdown 27 | 28 | 大家可能想为什么要使用markdown来写文档,而不用各种可以点击鼠标点点的那种所见即所得的工具来记笔记,例如word,云笔记之类的。 29 | 30 | 首先有如下几点: 31 | 32 | 1. Markdown可以在任何地方使用 33 | 34 | **可以使用它来创建网站,笔记,电子书,演讲稿,邮件信息和各种技术文档** 35 | 36 | 2. Markdown很轻便 37 | 38 | 事实上,**包含Markdown格式文本的文件可以被任何一个应用打开**。 39 | 40 | 如果感觉不喜欢当前使用的Markdown渲染应用,可以使用其他渲染应用来打开。 41 | 42 | 而鲜明对比的就是Microsoft Word,必须要使用特定的软件才能打开 .doc 或者 .docx的文档 而且可能还是乱码或者格式乱位。 43 | 44 | 3. Markdown是独立的平台 45 | 46 | **你可以创建Markdown格式文本的文件在任何一个可以运行的操作系统上** 47 | 48 | 4. Markdown已经无处不在 49 | 50 | **程序员的世界到处都是Markdown**,像简书,GitChat, GitHub,csdn等等都支持Markdown文档,正宗的官方技术文档都是使用Markdown来写的。 51 | 52 | 使用Markdown不仅可以非常方便的记录笔记,而且可以直接导出对应的网站内容,导出可打印的文档 53 | 54 | 至于markdown的语法,真的非常简单,不需要花费很长的时间掌握! 55 | 56 | 而且一旦你掌握了它,你就可以在任何地方任何平台使用Markdown来记录笔记,文档甚至写书。 57 | 58 | 很多人使用Markdown来创建网站的内容,但是Markdown更加擅长于格式化的文本内容,**使用Markdown 根部不用担心格式问题,兼容问题**。 59 | 60 | 很多后台开发程序员的工作环境是linux,linux下写文档最佳选择也是markdown。 61 | 62 | **我平时写代码,写文档都习惯在linux系统下进行(包括我的mac),所以我更喜欢vim + markdown**。 63 | 64 | 关于vim的话,后面我也可以单独介绍一波! 65 | 66 | ## Markdown常用语法 67 | 68 | 我这里就简单列举一些最基本的语法。 69 | 70 | ### 标题 71 | 72 | 使用'#' 可以展现1-6级别的标题 73 | 74 | ``` 75 | # 一级标题 76 | ## 二级标题 77 | ### 三级标题 78 | ``` 79 | 80 | ### 列表 81 | 82 | 使用 `*` 或者 `+` 或者 `-` 或者 `1. ` `2. ` 来表示列表 83 | 84 | 例如: 85 | 86 | ``` 87 | * 列表1 88 | * 列表2 89 | * 列表3 90 | ``` 91 | 92 | 效果: 93 | * 列表1 94 | * 列表2 95 | * 列表3 96 | 97 | ### 链接 98 | 99 | 使用 `[名字](url)` 表示连接,例如`[Github地址](https://github.com/youngyangyang04/Markdown-Resume-Template)` 100 | 101 | 102 | ### 添加图片 103 | 104 | 添加图片`![名字](图片地址)` 例如`![Minion](https://octodex.github.com/images/minion.png)` 105 | 106 | ### html 标签 107 | 108 | Markdown支持部分html,例如这样 109 | 110 | ``` 111 |

XXX

112 | ``` 113 | 114 | ## Markdown 渲染 115 | 116 | 有如下几种方式渲染Markdown文档 117 | 118 | * 使用github来渲染,也就是把自己的 .md 文件传到github上,就是有可视化的展现,大家会发现github上每个项目都有一个README.md 119 | * 使用谷歌浏览器安装MarkDown Preview Plus插件,也可以打开markdown文件,但是渲染效果不太好 120 | * mac下建议使用macdown来打开 markdown文件,然后就可以直接导出pdf来打印了 121 | * window下可以使用Typora来打开markdown文件,同样也可以直接导出pdf来打印 122 | 123 | ## Markdown学习资料 124 | 125 | 我这里仅仅是介绍了几个常用的语法,刚开始学习Markdown的时候语法难免会忘。 126 | 127 | 所以建议把这个markdown demo:https://markdown-it.github.io/ 收藏一下,平时用到哪里了忘了就看一看。 128 | 129 | 就酱,后面我还会陆续给大家安利一些编程利器。 130 | 131 | ## 总结 132 | 133 | 如果还没有掌握markdown的你还在等啥,赶紧使用markdown记录起来吧 134 | 135 | 136 | 137 | 138 | ----------------------- 139 |
140 | -------------------------------------------------------------------------------- /problems/0141.环形链表.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 |

参与本项目,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!

6 | 7 | 8 | # 141. 环形链表 9 | 10 | 给定一个链表,判断链表中是否有环。 11 | 12 | 如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。 13 | 14 | 如果链表中存在环,则返回 true 。 否则,返回 false 。 15 | 16 | ![](https://code-thinking-1253855093.file.myqcloud.com/pics/20210727173600.png) 17 | 18 | ## 思路 19 | 20 | 可以使用快慢指针法, 分别定义 fast 和 slow指针,从头结点出发,fast指针每次移动两个节点,slow指针每次移动一个节点,如果 fast 和 slow指针在途中相遇 ,说明这个链表有环。 21 | 22 | 为什么fast 走两个节点,slow走一个节点,有环的话,一定会在环内相遇呢,而不是永远的错开呢? 23 | 24 | 首先第一点: **fast指针一定先进入环中,如果fast 指针和slow指针相遇的话,一定是在环中相遇,这是毋庸置疑的。** 25 | 26 | 那么来看一下,**为什么fast指针和slow指针一定会相遇呢?** 27 | 28 | 可以画一个环,然后让 fast指针在任意一个节点开始追赶slow指针。 29 | 30 | 会发现最终都是这种情况, 如下图: 31 | 32 | 33 | 34 | fast和slow各自再走一步, fast和slow就相遇了 35 | 36 | 这是因为fast是走两步,slow是走一步,**其实相对于slow来说,fast是一个节点一个节点的靠近slow的**,所以fast一定可以和slow重合。 37 | 38 | 动画如下: 39 | 40 | 41 | ![141.环形链表](https://tva1.sinaimg.cn/large/e6c9d24ely1go4tquxo12g20fs0b6u0x.gif) 42 | 43 | 44 | C++代码如下 45 | 46 | ```CPP 47 | class Solution { 48 | public: 49 | bool hasCycle(ListNode *head) { 50 | ListNode* fast = head; 51 | ListNode* slow = head; 52 | while(fast != NULL && fast->next != NULL) { 53 | slow = slow->next; 54 | fast = fast->next->next; 55 | // 快慢指针相遇,说明有环 56 | if (slow == fast) return true; 57 | } 58 | return false; 59 | } 60 | }; 61 | ``` 62 | 63 | ## 扩展 64 | 65 | 做完这道题目,可以在做做[142.环形链表II](https://mp.weixin.qq.com/s/gt_VH3hQTqNxyWcl1ECSbQ),不仅仅要找环,还要找环的入口。 66 | 67 | 68 | 69 | ## 其他语言版本 70 | 71 | ### Java 72 | 73 | ```java 74 | public class Solution { 75 | public boolean hasCycle(ListNode head) { 76 | ListNode fast = head; 77 | ListNode slow = head; 78 | // 空链表、单节点链表一定不会有环 79 | while (fast != null && fast.next != null) { 80 | fast = fast.next.next; // 快指针,一次移动两步 81 | slow = slow.next; // 慢指针,一次移动一步 82 | if (fast == slow) { // 快慢指针相遇,表明有环 83 | return true; 84 | } 85 | } 86 | return false; // 正常走到链表末尾,表明没有环 87 | } 88 | } 89 | ``` 90 | 91 | ### Python 92 | 93 | ```python 94 | class Solution: 95 | def hasCycle(self, head: ListNode) -> bool: 96 | if not head: return False 97 | slow, fast = head, head 98 | while fast and fast.next: 99 | slow = slow.next 100 | fast = fast.next.next 101 | if fast == slow: 102 | return True 103 | return False 104 | ``` 105 | 106 | ## Go 107 | 108 | ```go 109 | ``` 110 | 111 | ### JavaScript 112 | 113 | ```js 114 | var hasCycle = function(head) { 115 | let fast = head; 116 | let slow = head; 117 | // 空链表、单节点链表一定不会有环 118 | while(fast != null && fast.next != null){ 119 | fast = fast.next.next; // 快指针,一次移动两步 120 | slow = slow.next; // 慢指针,一次移动一步 121 | if(fast === slow) return true; // 快慢指针相遇,表明有环 122 | } 123 | return false; // 正常走到链表末尾,表明没有环 124 | }; 125 | ``` 126 | 127 | 128 | ----------------------- 129 |
130 | -------------------------------------------------------------------------------- /problems/知识星球精选/秋招总结3.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 | # 秋招面试,心态很重要! 6 | 7 | 其实无论社招,还是校招,心态都很重要,例如,别人那个一堆offer,自己陷入深深的焦虑。 面试分明感觉自己表现的不错,结果就是挂了。面试中遇到了面试官的否定,然后就开始自我怀疑,等等等。 8 | 9 | 如果你也遇到这些问题,可以认真读完[知识星球](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ)里一位录友的总结,他是非科班,机械转码,今年5月份加入的星球,坚持打卡几个月,如果也获得自己心仪的offer,他的心路历程对大家会很有启发。 10 | 11 | ![](https://code-thinking-1253855093.file.myqcloud.com/pics/20211121093438.png) 12 | 13 | 以下原文: 14 | 15 | ---------------------- 16 | 17 | 写在最前:作为最一般的秋招选手,希望能对和我有相似经历的录友提供一些帮助。 18 | 19 | 1、个人情况:本硕211机械转码,无竞赛,无实习。转码原因:机械的工资真的不高,也不是很喜欢天天画图的生活;导师教本科C/C++语言,研一当助教重新学了一下C++。 20 | 21 | 2、加入星球: 22 | 23 | 3月份开学决定转码,3月到5月看C++primer和刷题,之前也是按题目顺序刷,效果一般。我是在LeetCode刷题的时候看到Carl哥的题解,然后关注随想录的GitHub,刷完链表在5.27决定加入的星球(那时还没有优惠,哈哈)现在也快半年了,那段时间是我最慌的时候,毕业课题没做完,秋招准备的也不行。刚看完C++ Primer,刷了几十题的状态。就是在星球打卡的这段时间学习比较认真,让我走过了比较难的一段路,感谢Carl哥的指导和各位录友的输出。(用Forest防止玩手机并记录了一下,6~9月平均学习15000分钟) 24 | 25 | 3、秋招历程: 26 | 27 | 6月到7月,C++基础就每天看一条《effective C++》,操作系统和计算机网络看书来不及就准备找网上大佬的精华过一遍然后直接面经。我找的是小林大佬的图解网络+图解操作系统,阿秀大佬的面经。(每日一问的主要来源)。 28 | 29 | 刷题大概每日一题+3道随想录+2剑指offer,7月完成一刷,8月底完成二刷。一刷的时候白天在LeetCode提交之后,晚上会在本子上手写总结一遍,理一理思路。二刷的时候就在Typora上快速记录了一下,节约时间。开始面试的时候题量:二刷完随想录+剑指offer,一共350题左右。在刷完以后可以上CodeTop刷各公司部门岗位的高频题。 30 | 31 | 7月份有的公司就陆陆续续开始提前批了,虽然知道提前批不需要笔试多一次机会,但是因为自己简历项目一块还比较单薄,一直没有进行投递。7月底买了《高性能服务器编程》一周多看完,然后做了一个基础的Web服务器,有不懂的就上网搜类似的解析。自己画了一下流程图之类的梳理了一下大概思路。第二个项目就是Carl哥的跳表项目,不是很长,主要是理解跳表这个数据结构,自己画一画就清楚了。 32 | 33 | 8月底开始投简历,对自己定位比较明确,主要以中厂为主,大厂随缘。8月底开始基本每天都有笔试,9月开始面试,一直到10月下旬结束秋招。面试的时候主要是录音,结束后进行面试总结,包括面试问题,手撕代码,面试表现(回答问题思路是否严谨,吐词是否清晰)。 34 | 35 | 其余关于实习,竞赛,面试的经验可以参考星球里其他大佬,哈哈哈。我感触比较深的是心态问题,这里写一写我自己遇到的心态问题和感想。 36 | 37 | 38 | 4、心态很重要: 39 | 40 | 心态问题1:同学或室友提前批就拿到了30大几w甚至更高的的offer,自己才开始笔试,说不羡慕是不可能的,有几天晚上都有一点焦虑没有睡好。这可能是因为自己并没有全力以赴,害怕因为自己的不努力而失去机会,后来每天都在按计划学习,每天都比较充实,抱着努力不后悔的心态。当你一心学习的时候就不太会一直考虑让自己焦虑的问题,总之一句话,冲就完事了。 41 | 42 | 心态问题2:总感觉自己没有准备好而不敢投简历。项目没准备或者面经记得不熟。其实投了简历以后还会有一段时间,包括HR筛简历,测评笔试才到面试,所以能投尽早投,在面试之前有压力的时候复习效率比较高的。 43 | 44 | 心态问题3:面试时的心态:心里默念一定要思考一下,然后慢慢说。我有一次面试,前面几个问题不是很顺利,然后问了我一个我会的,我就把我想到的一股脑说出来,我想着终于遇到一个我会的了,自我感觉良好,结果面试结束复盘的时候才发现,那个问题说的不是很全面而且说的比较快,面试官感觉可能很一般。 45 | 46 | 心态问题4:有时可能会紧张的不行,导致本来自己知道或者有思路而因为紧张语无伦次没有表达出来,从而影响面试表现(可以事先准备好自我介绍,流畅的自我介绍在一定程度上可以建立信心,减缓紧张。参加一些模拟面试,找同学模拟或者在网上模拟,还可以录一下视频,看一下自己的表现怎样,有什么地方需要注意;找一些中小厂练手实战也不错) 47 | 48 | 心态问题5:面试后的心态,可能有时候觉得自己表现还不错但是面试挂了而愤愤不平,或者和同学一起面一家公司,同学过了,自己挂了。这个时候需要把心态放平,及时总结自己的面试表现,可能没有你想象的那么好。而且面试主观因素挺多的,结果和面试官有很大关系,所以做好自己,尽人事听天命。 49 | 50 | 心态问题6:面试过程中可能会遇到比较不好的面试官,导致面试体验比较差而影响自己的心态,这个时候也是需要及时发泄,不要自我否定或赌气,想着后面还有更多的机会,把更多精力投入到下一次面试或笔试中。我遇到的面试官都比较nice的,希望大家也一样! 51 | 52 | 5、写在最后: 53 | 54 | 最后对主要面试结果做一个总结:腾讯(笔试挂),百度(二面挂),最后拿到的:华为通用软开,深信服C++开发,科大讯飞C++,中电28所,30所。最后选择离家近的成都华为,总的来说虽然没去成大厂,但是自己已经很满意了。 55 | 56 | 最后的最后:说的有点多,比较啰嗦,感谢大家能看完。希望大家一定不要放弃,相信自己,能拿到自己想要的offer!! 57 | 58 | --------------- 59 | 60 | 可以看一下这篇总结在星球下的评论: 61 | 62 | ![](https://code-thinking-1253855093.file.myqcloud.com/pics/20211121094859.png) 63 | 64 | **他在星球里知名度还是很高的,为啥知名度这么高呢?** 65 | 66 | 因为他坚持几个月的打卡,而且打卡质量非常高,所以星球里的录友们都认识他。 67 | 68 | 来看看他的打卡内容: 69 | 70 | ![](https://code-thinking-1253855093.file.myqcloud.com/pics/20211121095337.png) 71 | 72 | ![](https://code-thinking-1253855093.file.myqcloud.com/pics/20211121095415.png) 73 | 74 | ![](https://code-thinking-1253855093.file.myqcloud.com/pics/20211121095712.png) 75 | 76 | 我只是随便选了几条,他有将近200条的打卡记录,如果大家也在准备明年秋招,可以进星球里看看他的每日的打卡记录,相信会对规划自己的学习计划,任务安排 都很有帮助。 77 | 78 | 而且星球里的学习氛围会让你惊讶,原来有这么多大佬,还这么努力。 79 | 80 | ![星球氛围好](https://code-thinking-1253855093.file.myqcloud.com/pics/20211018000722.png) 81 | 82 | ![看星球里的内容收获满满](https://code-thinking-1253855093.file.myqcloud.com/pics/20211025182654.png) 83 | 84 | -------------------------------------------------------------------------------- /problems/周总结/20201210复杂度分析周末总结.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |

5 | 6 | 7 | 8 | 9 |

10 | 11 | 12 | 正好也给「算法汇总」添加一个新专题-算法性能分析,以后如果有空余时间还会陆续更新这个模块,大家如果经常看「算法汇总」的话,就会发现,「算法汇总」里已经更新的三个模块「编程素养」「求职」「算法性能分析」,内容越来越丰满了,大家现在就可以去看看哈。 13 | 14 | 后面在算法题目之余,我还会继续更新这几个模块的! 15 | 16 | # 周一 17 | 18 | 在[程序员的简历应该这么写!!(附简历模板)](https://programmercarl.com/前序/程序员简历.html)中以我自己的总结经验为例讲一讲大家应该如何写简历。 19 | 20 | 主要有如下几点: 21 | 22 | * 简历篇幅不要过长 23 | * 谨慎使用“精通” 24 | * 拿不准的绝对不要写在简历上 25 | * 项目经验中要突出自己的贡献 26 | * 面试中如何变被动为主动 27 | * 博客的重要性 28 | 29 | 最后还给出我自己的简历模板。 30 | 31 | 每一个点我都在文章中详细讲解了应该怎么写,平时应该如何积累,以及面前如何准备。 32 | 33 | 如果大家把以上几点都注意到了,那就是一份优秀的简历了,至少简历上就没啥毛病,剩下的就看自己的技术功底和临场发挥了。 34 | 35 | 一些录友会问我学校不好怎么办,没有项目经验怎么办之类的问题。 36 | 37 | 其实这就不在简历技巧的范围内了。 38 | 39 | 对于学校的话,某些公司可能有硬性要求,但如果能力特别出众,机会也是很大的。 不过说实话,大家都是普通人,真正技术能力出众的选手毕竟是少数。 40 | 41 | **而且面试其实挺看缘分的**,相信大家应该都遇到过这种情景:同一家公司面别人的时候问题贼简单,然后人家就顺利拿offer,一到自己面的时候难题就上来了。 42 | 43 | 至于项目经验,没有项目,就要自己找找项目来做。 44 | 45 | 我的Github上有一些我曾经写过的一些小项目,大家可以去看看:https://github.com/youngyangyang04 46 | 47 | **最后就是要端正写简历的心态,写简历是在自己真实背景和水平下,把自己各个方面包装到极致!** 48 | 49 | 50 | # 周二 51 | 52 | 在[关于时间复杂度,你不知道的都在这里!](https://programmercarl.com/前序/关于时间复杂度,你不知道的都在这里!.html)中详细讲解了时间复杂度,很多被大家忽略的内容,在文中都做了详细的解释。 53 | 54 | 文中涉及如下问题: 55 | 56 | * 究竟什么是大O?大O表示什么意思?严格按照大O的定义来说,快排应该是$O(n^2)$的算法! 57 | * $O(n^2)$的算法为什么有时候比$O(n)$的算法更优? 58 | * 什么时间复杂度为什么可以忽略常数项? 59 | * 如何简化复杂的时间复杂度表达式,原理是什么? 60 | * $O(\log n)$中的log究竟是以谁为底? 61 | 62 | 这些问题大家可能懵懵懂懂的了解一些,但一细问又答不上来。 63 | 64 | 相信看完本篇[关于时间复杂度,你不知道的都在这里!](https://programmercarl.com/前序/关于时间复杂度,你不知道的都在这里!.html),以上问题大家就理解的清晰多了。 65 | 66 | 文中最后还运用以上知识通过一道简单的题目具体分析了一下其时间复杂度,给出两种方法究竟谁最优。 67 | 68 | 可以说从理论到实战将时间复杂度讲的明明白白。 69 | 70 | 71 | # 周三 72 | 73 | 在[$O(n)$的算法居然超时了,此时的n究竟是多大?](https://programmercarl.com/前序/On的算法居然超时了,此时的n究竟是多大?.html)中介绍了大家在leetcode上提交代码经常遇到的一个问题-超时! 74 | 75 | 估计很多录友知道算法超时了,但没有注意过 $O(n)$的算法,如果1s内出结果,这个n究竟是多大? 76 | 77 | 文中从计算机硬件出发,分析计算机的计算性能,然后亲自做实验,整理出数据如下: 78 | 79 | ![程序超时1](https://img-blog.csdnimg.cn/20201208231559175.png) 80 | 81 | **大家有一个数量级上的概念就可以了!** 82 | 83 | 正如文中说到的,**作为一名合格的程序员,至少要知道我们的程序是1s后出结果还是一年后出结果**。 84 | 85 | 86 | # 周四 87 | 88 | 在[通过一道面试题目,讲一讲递归算法的时间复杂度!](https://programmercarl.com/前序/通过一道面试题目,讲一讲递归算法的时间复杂度!.html)中,讲一讲如果计算递归算法的时间复杂度。 89 | 90 | 递归的时间复杂度等于**递归的次数 * 每次递归中的操作次数**。 91 | 92 | 所以了解究竟递归了多少次就是重点。 93 | 94 | 文中通过一道简单的面试题:求x的n次方(**注意:这道面试题大厂面试官经常用!**),还原面试场景,来带大家深入了解一下递归的时间复杂度。 95 | 96 | 文中给出了四个版本的代码实现,并逐一分析了其时间复杂度。 97 | 98 | 此时大家就会发现,同一道题目,同样使用递归算法,有的同学会写出了$O(n)$的代码,有的同学就写出了$O(\log n)$的代码。 99 | 100 | 其本质是要对递归的时间复杂度有清晰的认识,才能运用递归来有效的解决问题! 101 | 102 | 相信看了本篇之后,对递归的时间复杂度分析就已经有深刻的理解了。 103 | 104 | 105 | # 总结 106 | 107 | 本周讲解的内容都是经常被大家忽略的知识点,而通常这种知识点,才最能发现一位候选人的编程功底。 108 | 109 | 因为之前一直都是在持续更新算法题目的文章,这周说一说算法性能分析,感觉也是换了换口味,哈哈。 110 | 111 | 同时大家也会发现,**大厂面试官最喜欢用“简单题”(就是看起来很简单,其实非常考验技术功底的题目),而不是要手撕红黑树之类的**。 112 | 113 | 所以基础很重要,本周我介绍的内容其实都不难,看过的话都懂了,都是基础内容,但很多同学都把这些内容忽略掉了。 114 | 115 | 这其实也正常,咱们上学的时候教科书上基本没有实用的重点,而一般求职算法书也不讲这些,所以这方面内容可以靠看「代码随想录」的文章,当然更要靠自己多琢磨,多专研,多实践! 116 | 117 | **下周开始恢复贪心题目系列**,后序有空我还会陆续讲一讲类似本周的基础内容,在「算法汇总」的那几个模块都会持续更新的。 118 | 119 | 就酱,「代码随想录」是技术公众号里的一抹清流,值得推荐给身边的朋友同学们! 120 | 121 | 122 |
123 | -------------------------------------------------------------------------------- /problems/周总结/20201017二叉树周末总结.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 本周小结!(二叉树系列四) 4 | 5 | > 这已经是二叉树的第四周总结了,二叉树是非常重要的数据结构,也是面试中的常客,所以有必要一步一步帮助大家彻底掌握二叉树! 6 | 7 | ## 周一 8 | 9 | 在[二叉树:合并两个二叉树](https://programmercarl.com/0617.合并二叉树.html)中讲解了如何合并两个二叉树,平时我们都习惯了操作一个二叉树,一起操作两个树可能还有点陌生。 10 | 11 | 其实套路是一样,只不过一起操作两个树的指针,我们之前讲过求 [二叉树:我对称么?](https://programmercarl.com/0101.对称二叉树.html)的时候,已经初步涉及到了 一起遍历两棵二叉树了。 12 | 13 | **迭代法中,一般一起操作两个树都是使用队列模拟类似层序遍历,同时处理两个树的节点,这种方式最好理解,如果用模拟递归的思路的话,要复杂一些。** 14 | 15 | ## 周二 16 | 17 | 周二开始讲解一个新的树,二叉搜索树,开始要换一个思路了,如果没有利用好二叉搜索树的特性,就容易把简单题做成了难题了。 18 | 19 | 学习[二叉搜索树的特性](https://programmercarl.com/0700.二叉搜索树中的搜索.html),还是比较容易的。 20 | 21 | 大多是二叉搜索树的题目,其实都离不开中序遍历,因为这样就是有序的。 22 | 23 | 至于迭代法,相信大家看到文章中如此简单的迭代法的时候,都会感动的痛哭流涕。 24 | 25 | ## 周三 26 | 27 | 了解了二搜索树的特性之后, 开始验证[一棵二叉树是不是二叉搜索树](https://programmercarl.com/0098.验证二叉搜索树.html)。 28 | 29 | 首先在此强调一下二叉搜索树的特性: 30 | 31 | * 节点的左子树只包含小于当前节点的数。 32 | * 节点的右子树只包含大于当前节点的数。 33 | * 所有左子树和右子树自身必须也是二叉搜索树。 34 | 35 | 那么我们在验证二叉搜索树的时候,有两个陷阱: 36 | 37 | * 陷阱一 38 | 39 | **不能单纯的比较左节点小于中间节点,右节点大于中间节点就完事了**,而是左子树都小于中间节点,右子树都大于中间节点。 40 | 41 | * 陷阱二 42 | 43 | 在一个有序序列求最值的时候,不要定义一个全局遍历,然后遍历序列更新全局变量求最值。因为最值可能就是int 或者 longlong的最小值。 44 | 45 | 推荐要通过前一个数值(pre)和后一个数值比较(cur),得出最值。 46 | 47 | **在二叉树中通过两个前后指针作比较,会经常用到**。 48 | 49 | 本文[二叉树:我是不是一棵二叉搜索树](https://programmercarl.com/0098.验证二叉搜索树.html)中迭代法中为什么没有周一那篇那么简洁了呢,因为本篇是验证二叉搜索树,前提默认它是一棵普通二叉树,所以还是要回归之前老办法。 50 | 51 | ## 周四 52 | 53 | 了解了[二叉搜索树](https://programmercarl.com/0700.二叉搜索树中的搜索.html),并且知道[如何判断二叉搜索树](https://programmercarl.com/0098.验证二叉搜索树.html),本篇就很简单了。 54 | 55 | **要知道二叉搜索树和中序遍历是好朋友!** 56 | 57 | 在[二叉树:搜索树的最小绝对差](https://programmercarl.com/0530.二叉搜索树的最小绝对差.html)中强调了要利用搜索树的特性,把这道题目想象成在一个有序数组上求两个数最小差值,这就是一道送分题了。 58 | 59 | **需要明确:在有序数组求任意两数最小值差等价于相邻两数的最小值差**。 60 | 61 | 同样本题也需要用pre节点记录cur节点的前一个节点。(这种写法一定要掌握) 62 | 63 | ## 周五 64 | 65 | 此时大家应该知道遇到二叉搜索树,就想是有序数组,那么在二叉搜索树中求二叉搜索树众数就很简单了。 66 | 67 | 在[二叉树:我的众数是多少?](https://programmercarl.com/0501.二叉搜索树中的众数.html)中我给出了如果是普通二叉树,应该如何求众数的集合,然后进一步讲解了二叉搜索树应该如何求众数集合。 68 | 69 | 在求众数集合的时候有一个技巧,因为题目中众数是可以有多个的,所以一般的方法需要遍历两遍才能求出众数的集合。 70 | 71 | **但可以遍历一遍就可以求众数集合,使用了适时清空结果集的方法**,这个方法还是很巧妙的。相信仔细读了文章的同学会惊呼其巧妙! 72 | 73 | **所以大家不要看题目简单了,就不动手做了,我选的题目,一般不会简单到不用动手的程度,哈哈**。 74 | 75 | ## 周六 76 | 77 | 在[二叉树:公共祖先问题](https://programmercarl.com/0236.二叉树的最近公共祖先.html)中,我们开始讲解如何在二叉树中求公共祖先的问题,本来是打算和二叉搜索树一起讲的,但发现篇幅过长,所以先讲二叉树的公共祖先问题。 78 | 79 | **如果找到一个节点,发现左子树出现结点p,右子树出现节点q,或者 左子树出现结点q,右子树出现节点p,那么该节点就是节点p和q的最近公共祖先。** 80 | 81 | 这道题目的看代码比较简单,而且好像也挺好理解的,但是如果把每一个细节理解到位,还是不容易的。 82 | 83 | 主要思考如下几点: 84 | 85 | * 如何从底向上遍历? 86 | * 遍历整棵树,还是遍历局部树? 87 | * 如何把结果传到根节点的? 88 | 89 | 这些问题都需要弄清楚,上来直接看代码的话,是可能想不到这些细节的。 90 | 91 | 公共祖先问题,还是有难度的,初学者还是需要慢慢消化! 92 | 93 | ## 总结 94 | 95 | 本周我们讲了[如何合并两个二叉树](https://programmercarl.com/0617.合并二叉树.html),了解了如何操作两个二叉树。 96 | 97 | 然后开始另一种树:二叉搜索树,了解[二叉搜索树的特性](https://programmercarl.com/0700.二叉搜索树中的搜索.html),然后[判断一棵二叉树是不是二叉搜索树](https://programmercarl.com/0098.验证二叉搜索树.html)。 98 | 99 | 了解以上知识之后,就开始利用其特性,做一些二叉搜索树上的题目,[求最小绝对差](https://programmercarl.com/0530.二叉搜索树的最小绝对差.html),[求众数集合](https://programmercarl.com/0501.二叉搜索树中的众数.html)。 100 | 101 | 接下来,开始求二叉树与二叉搜索树的公共祖先问题,单篇篇幅原因,先单独介绍[普通二叉树如何求最近公共祖先](https://programmercarl.com/0236.二叉树的最近公共祖先.html)。 102 | 103 | 现在已经讲过了几种二叉树了,二叉树,二叉平衡树,完全二叉树,二叉搜索树,后面还会有平衡二叉搜索树。 那么一些同学难免会有混乱了,我针对如下三个问题,帮大家在捋顺一遍: 104 | 105 | 1. 平衡二叉搜索数是不是二叉搜索树和平衡二叉树的结合? 106 | 107 | 是的,是二叉搜索树和平衡二叉树的结合。 108 | 109 | 2. 平衡二叉树与完全二叉树的区别在于底层节点的位置? 110 | 111 | 是的,完全二叉树底层必须是从左到右连续的,且次底层是满的。 112 | 113 | 3. 堆是完全二叉树和排序的结合,而不是平衡二叉搜索树? 114 | 115 | 堆是一棵完全二叉树,同时保证父子节点的顺序关系(有序)。 **但完全二叉树一定是平衡二叉树,堆的排序是父节点大于子节点,而搜索树是父节点大于左孩子,小于右孩子,所以堆不是平衡二叉搜索树**。 116 | 117 | 大家如果每天坚持跟下来,会发现又是充实的一周![机智] 118 | 119 |
120 | -------------------------------------------------------------------------------- /problems/动态规划理论基础.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 |

参与本项目,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!

6 | 7 | # 动态规划理论基础 8 | 9 | 动态规划刷题大纲 10 | 11 | 12 | 13 | ## 什么是动态规划 14 | 15 | 动态规划,英文:Dynamic Programming,简称DP,如果某一问题有很多重叠子问题,使用动态规划是最有效的。 16 | 17 | 所以动态规划中每一个状态一定是由上一个状态推导出来的,**这一点就区分于贪心**,贪心没有状态推导,而是从局部直接选最优的, 18 | 19 | 在[关于贪心算法,你该了解这些!](https://mp.weixin.qq.com/s/A9MHJi1a5uugFaqp8QJFWg)中我举了一个背包问题的例子。 20 | 21 | 例如:有N件物品和一个最多能背重量为W 的背包。第i件物品的重量是weight[i],得到的价值是value[i] 。**每件物品只能用一次**,求解将哪些物品装入背包里物品价值总和最大。 22 | 23 | 动态规划中dp[j]是由dp[j-weight[i]]推导出来的,然后取max(dp[j], dp[j - weight[i]] + value[i])。 24 | 25 | 但如果是贪心呢,每次拿物品选一个最大的或者最小的就完事了,和上一个状态没有关系。 26 | 27 | 所以贪心解决不了动态规划的问题。 28 | 29 | **其实大家也不用死扣动规和贪心的理论区别,后面做做题目自然就知道了**。 30 | 31 | 而且很多讲解动态规划的文章都会讲最优子结构啊和重叠子问题啊这些,这些东西都是教科书的上定义,晦涩难懂而且不实用。 32 | 33 | 大家知道动规是由前一个状态推导出来的,而贪心是局部直接选最优的,对于刷题来说就够用了。 34 | 35 | 上述提到的背包问题,后序会详细讲解。 36 | 37 | ## 动态规划的解题步骤 38 | 39 | 做动规题目的时候,很多同学会陷入一个误区,就是以为把状态转移公式背下来,照葫芦画瓢改改,就开始写代码,甚至把题目AC之后,都不太清楚dp[i]表示的是什么。 40 | 41 | **这就是一种朦胧的状态,然后就把题给过了,遇到稍稍难一点的,可能直接就不会了,然后看题解,然后继续照葫芦画瓢陷入这种恶性循环中**。 42 | 43 | 状态转移公式(递推公式)是很重要,但动规不仅仅只有递推公式。 44 | 45 | **对于动态规划问题,我将拆解为如下五步曲,这五步都搞清楚了,才能说把动态规划真的掌握了!** 46 | 47 | 1. 确定dp数组(dp table)以及下标的含义 48 | 2. 确定递推公式 49 | 3. dp数组如何初始化 50 | 4. 确定遍历顺序 51 | 5. 举例推导dp数组 52 | 53 | 一些同学可能想为什么要先确定递推公式,然后在考虑初始化呢? 54 | 55 | **因为一些情况是递推公式决定了dp数组要如何初始化!** 56 | 57 | 后面的讲解中我都是围绕着这五点来进行讲解。 58 | 59 | 可能刷过动态规划题目的同学可能都知道递推公式的重要性,感觉确定了递推公式这道题目就解出来了。 60 | 61 | 其实 确定递推公式 仅仅是解题里的一步而已! 62 | 63 | 一些同学知道递推公式,但搞不清楚dp数组应该如何初始化,或者正确的遍历顺序,以至于记下来公式,但写的程序怎么改都通过不了。 64 | 65 | 后序的讲解的大家就会慢慢感受到这五步的重要性了。 66 | 67 | ## 动态规划应该如何debug 68 | 69 | 70 | 相信动规的题目,很大部分同学都是这样做的。 71 | 72 | 看一下题解,感觉看懂了,然后照葫芦画瓢,如果能正好画对了,万事大吉,一旦要是没通过,就怎么改都通过不了,对 dp数组的初始化,递推公式,遍历顺序,处于一种黑盒的理解状态。 73 | 74 | 写动规题目,代码出问题很正常! 75 | 76 | **找问题的最好方式就是把dp数组打印出来,看看究竟是不是按照自己思路推导的!** 77 | 78 | 一些同学对于dp的学习是黑盒的状态,就是不清楚dp数组的含义,不懂为什么这么初始化,递推公式背下来了,遍历顺序靠习惯就是这么写的,然后一鼓作气写出代码,如果代码能通过万事大吉,通过不了的话就凭感觉改一改。 79 | 80 | 这是一个很不好的习惯! 81 | 82 | **做动规的题目,写代码之前一定要把状态转移在dp数组的上具体情况模拟一遍,心中有数,确定最后推出的是想要的结果**。 83 | 84 | 然后再写代码,如果代码没通过就打印dp数组,看看是不是和自己预先推导的哪里不一样。 85 | 86 | 如果打印出来和自己预先模拟推导是一样的,那么就是自己的递归公式、初始化或者遍历顺序有问题了。 87 | 88 | 如果和自己预先模拟推导的不一样,那么就是代码实现细节有问题。 89 | 90 | **这样才是一个完整的思考过程,而不是一旦代码出问题,就毫无头绪的东改改西改改,最后过不了,或者说是稀里糊涂的过了**。 91 | 92 | 这也是我为什么在动规五步曲里强调推导dp数组的重要性。 93 | 94 | 举个例子哈:在「代码随想录」刷题小分队微信群里,一些录友可能代码通过不了,会把代码抛到讨论群里问:我这里代码都已经和题解一模一样了,为什么通过不了呢? 95 | 96 | 发出这样的问题之前,其实可以自己先思考这三个问题: 97 | 98 | * 这道题目我举例推导状态转移公式了么? 99 | * 我打印dp数组的日志了么? 100 | * 打印出来了dp数组和我想的一样么? 101 | 102 | **如果这灵魂三问自己都做到了,基本上这道题目也就解决了**,或者更清晰的知道自己究竟是哪一点不明白,是状态转移不明白,还是实现代码不知道该怎么写,还是不理解遍历dp数组的顺序。 103 | 104 | 然后在问问题,目的性就很强了,群里的小伙伴也可以快速知道提问者的疑惑了。 105 | 106 | **注意这里不是说不让大家问问题哈, 而是说问问题之前要有自己的思考,问题要问到点子上!** 107 | 108 | **大家工作之后就会发现,特别是大厂,问问题是一个专业活,是的,问问题也要体现出专业!** 109 | 110 | 如果问同事很不专业的问题,同事们会懒的回答,领导也会认为你缺乏思考能力,这对职场发展是很不利的。 111 | 112 | 所以大家在刷题的时候,就锻炼自己养成专业提问的好习惯。 113 | 114 | ## 总结 115 | 116 | 这一篇是动态规划的整体概述,讲解了什么是动态规划,动态规划的解题步骤,以及如何debug。 117 | 118 | 动态规划是一个很大的领域,今天这一篇讲解的内容是整个动态规划系列中都会使用到的一些理论基础。 119 | 120 | 在后序讲解中针对某一具体问题,还会讲解其对应的理论基础,例如背包问题中的01背包,leetcode上的题目都是01背包的应用,而没有纯01背包的问题,那么就需要在把对应的理论知识讲解一下。 121 | 122 | 大家会发现,我讲解的理论基础并不是教科书上各种动态规划的定义,错综复杂的公式。 123 | 124 | 这里理论基础篇已经是非常偏实用的了,每个知识点都是在解题实战中非常有用的内容,大家要重视起来哈。 125 | 126 | 今天我们开始新的征程了,你准备好了么? 127 | 128 | 129 | ----------------------- 130 |
131 | -------------------------------------------------------------------------------- /problems/背包总结篇.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 |

参与本项目,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!

6 | # 听说背包问题很难? 这篇总结篇来拯救你了 7 | 8 | 年前我们已经把背包问题都讲完了,那么现在我们要对背包问题进行总结一番。 9 | 10 | 背包问题是动态规划里的非常重要的一部分,所以我把背包问题单独总结一下,等动态规划专题更新完之后,我们还会在整体总结一波动态规划。 11 | 12 | 关于这几种常见的背包,其关系如下: 13 | 14 | ![416.分割等和子集1](https://img-blog.csdnimg.cn/20210117171307407.png) 15 | 16 | 通过这个图,可以很清晰分清这几种常见背包之间的关系。 17 | 18 | 在讲解背包问题的时候,我们都是按照如下五部来逐步分析,相信大家也体会到,把这五部都搞透了,算是对动规来理解深入了。 19 | 20 | 1. 确定dp数组(dp table)以及下标的含义 21 | 2. 确定递推公式 22 | 3. dp数组如何初始化 23 | 4. 确定遍历顺序 24 | 5. 举例推导dp数组 25 | 26 | **其实这五部里哪一步都很关键,但确定递推公式和确定遍历顺序都具有规律性和代表性,所以下面我从这两点来对背包问题做一做总结**。 27 | 28 | ## 背包递推公式 29 | 30 | 问能否能装满背包(或者最多装多少):dp[j] = max(dp[j], dp[j - nums[i]] + nums[i]); ,对应题目如下: 31 | * [动态规划:416.分割等和子集](https://programmercarl.com/0416.分割等和子集.html) 32 | * [动态规划:1049.最后一块石头的重量 II](https://programmercarl.com/1049.最后一块石头的重量II.html) 33 | 34 | 问装满背包有几种方法:dp[j] += dp[j - nums[i]] ,对应题目如下: 35 | * [动态规划:494.目标和](https://programmercarl.com/0494.目标和.html) 36 | * [动态规划:518. 零钱兑换 II](https://programmercarl.com/0518.零钱兑换II.html) 37 | * [动态规划:377.组合总和Ⅳ](https://programmercarl.com/0377.组合总和Ⅳ.html) 38 | * [动态规划:70. 爬楼梯进阶版(完全背包)](https://programmercarl.com/0070.爬楼梯完全背包版本.html) 39 | 40 | 问背包装满最大价值:dp[j] = max(dp[j], dp[j - weight[i]] + value[i]); ,对应题目如下: 41 | * [动态规划:474.一和零](https://programmercarl.com/0474.一和零.html) 42 | 43 | 问装满背包所有物品的最小个数:dp[j] = min(dp[j - coins[i]] + 1, dp[j]); ,对应题目如下: 44 | * [动态规划:322.零钱兑换](https://programmercarl.com/0322.零钱兑换.html) 45 | * [动态规划:279.完全平方数](https://programmercarl.com/0279.完全平方数.html) 46 | 47 | 48 | ## 遍历顺序 49 | 50 | ### 01背包 51 | 52 | 在[动态规划:关于01背包问题,你该了解这些!](https://programmercarl.com/背包理论基础01背包-1.html)中我们讲解二维dp数组01背包先遍历物品还是先遍历背包都是可以的,且第二层for循环是从小到大遍历。 53 | 54 | 和[动态规划:关于01背包问题,你该了解这些!(滚动数组)](https://programmercarl.com/背包理论基础01背包-2.html)中,我们讲解一维dp数组01背包只能先遍历物品再遍历背包容量,且第二层for循环是从大到小遍历。 55 | 56 | **一维dp数组的背包在遍历顺序上和二维dp数组实现的01背包其实是有很大差异的,大家需要注意!** 57 | 58 | ### 完全背包 59 | 60 | 说完01背包,再看看完全背包。 61 | 62 | 在[动态规划:关于完全背包,你该了解这些!](https://programmercarl.com/背包问题理论基础完全背包.html)中,讲解了纯完全背包的一维dp数组实现,先遍历物品还是先遍历背包都是可以的,且第二层for循环是从小到大遍历。 63 | 64 | 但是仅仅是纯完全背包的遍历顺序是这样的,题目稍有变化,两个for循环的先后顺序就不一样了。 65 | 66 | **如果求组合数就是外层for循环遍历物品,内层for遍历背包**。 67 | 68 | **如果求排列数就是外层for遍历背包,内层for循环遍历物品**。 69 | 70 | 相关题目如下: 71 | 72 | * 求组合数:[动态规划:518.零钱兑换II](https://programmercarl.com/0518.零钱兑换II.html) 73 | * 求排列数:[动态规划:377. 组合总和 Ⅳ](https://mp.weixin.qq.com/s/Iixw0nahJWQgbqVNk8k6gA)、[动态规划:70. 爬楼梯进阶版(完全背包)](https://programmercarl.com/0070.爬楼梯完全背包版本.html) 74 | 75 | 如果求最小数,那么两层for循环的先后顺序就无所谓了,相关题目如下: 76 | 77 | * 求最小数:[动态规划:322. 零钱兑换](https://programmercarl.com/0322.零钱兑换.html)、[动态规划:279.完全平方数](https://programmercarl.com/0279.完全平方数.html) 78 | 79 | 80 | **对于背包问题,其实递推公式算是容易的,难是难在遍历顺序上,如果把遍历顺序搞透,才算是真正理解了**。 81 | 82 | 83 | ## 总结 84 | 85 | 86 | **这篇背包问题总结篇是对背包问题的高度概括,讲最关键的两部:递推公式和遍历顺序,结合力扣上的题目全都抽象出来了**。 87 | 88 | **而且每一个点,我都给出了对应的力扣题目**。 89 | 90 | 最后如果你想了解多重背包,可以看这篇[动态规划:关于多重背包,你该了解这些!](https://programmercarl.com/背包问题理论基础多重背包.html),力扣上还没有多重背包的题目,也不是面试考察的重点。 91 | 92 | 如果把我本篇总结出来的内容都掌握的话,可以说对背包问题理解的就很深刻了,用来对付面试中的背包问题绰绰有余! 93 | 94 | 背包问题总结: 95 | 96 | ![](https://code-thinking-1253855093.file.myqcloud.com/pics/背包问题1.jpeg) 97 | 98 | 这个图是 [代码随想录知识星球](https://programmercarl.com/other/kstar.html) 成员:[海螺人](https://wx.zsxq.com/dweb2/index/footprint/844412858822412),所画结的非常好,分享给大家。 99 | 100 | 101 | 102 | 103 | ----------------------- 104 |
105 | -------------------------------------------------------------------------------- /problems/数组总结篇.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 |

参与本项目,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!

6 | 7 | 8 | 9 | # 数组理论基础 10 | 11 | 数组是非常基础的数据结构,在面试中,考察数组的题目一般在思维上都不难,主要是考察对代码的掌控能力 12 | 13 | 也就是说,想法很简单,但实现起来 可能就不是那么回事了。 14 | 15 | 首先要知道数组在内存中的存储方式,这样才能真正理解数组相关的面试题 16 | 17 | **数组是存放在连续内存空间上的相同类型数据的集合。** 18 | 19 | 数组可以方便的通过下标索引的方式获取到下标下对应的数据。 20 | 21 | 举一个字符数组的例子,如图所示: 22 | 23 | 24 | 25 | 需要两点注意的是 26 | 27 | * **数组下标都是从0开始的。** 28 | * **数组内存空间的地址是连续的** 29 | 30 | 正是**因为数组的在内存空间的地址是连续的,所以我们在删除或者增添元素的时候,就难免要移动其他元素的地址。** 31 | 32 | 例如删除下标为3的元素,需要对下标为3的元素后面的所有元素都要做移动操作,如图所示: 33 | 34 | 35 | 36 | 而且大家如果使用C++的话,要注意vector 和 array的区别,vector的底层实现是array,严格来讲vector是容器,不是数组。 37 | 38 | **数组的元素是不能删的,只能覆盖。** 39 | 40 | 那么二维数组直接上图,大家应该就知道怎么回事了 41 | 42 | 43 | 44 | **那么二维数组在内存的空间地址是连续的么?** 45 | 46 | 我们来举一个例子,例如: `int[][] rating = new int[3][4];` , 这个二维数据在内存空间可不是一个 `3*4` 的连续地址空间 47 | 48 | 看了下图,就应该明白了: 49 | 50 | 51 | 52 | 所以**二维数据在内存中不是 `3*4` 的连续地址空间,而是四条连续的地址空间组成!** 53 | 54 | # 数组的经典题目 55 | 56 | 在面试中,数组是必考的基础数据结构。 57 | 58 | 其实数据的题目在思想上一般比较简单的,但是如果想高效,并不容易。 59 | 60 | 我们之前一共讲解了四道经典数组题目,每一道题目都代表一个类型,一种思想。 61 | 62 | ## 二分法 63 | 64 | [数组:每次遇到二分法,都是一看就会,一写就废](https://programmercarl.com/0704.二分查找.html) 65 | 66 | 这道题目呢,考察数组的基本操作,思路很简单,但是通过率在简单题里并不高,不要轻敌。 67 | 68 | 可以使用暴力解法,通过这道题目,如果追求更优的算法,建议试一试用二分法,来解决这道题目 69 | 70 | * 暴力解法时间复杂度:$O(n)$ 71 | * 二分法时间复杂度:$O(\log n)$ 72 | 73 | 在这道题目中我们讲到了**循环不变量原则**,只有在循环中坚持对区间的定义,才能清楚的把握循环中的各种细节。 74 | 75 | **二分法是算法面试中的常考题,建议通过这道题目,锻炼自己手撕二分的能力**。 76 | 77 | 78 | ## 双指针法 79 | 80 | * [数组:就移除个元素很难么?](https://programmercarl.com/0027.移除元素.html) 81 | 82 | 双指针法(快慢指针法):**通过一个快指针和慢指针在一个for循环下完成两个for循环的工作。** 83 | 84 | * 暴力解法时间复杂度:$O(n^2)$ 85 | * 双指针时间复杂度:$O(n)$ 86 | 87 | 这道题目迷惑了不少同学,纠结于数组中的元素为什么不能删除,主要是因为以下两点: 88 | 89 | * 数组在内存中是连续的地址空间,不能释放单一元素,如果要释放,就是全释放(程序运行结束,回收内存栈空间)。 90 | * C++中vector和array的区别一定要弄清楚,vector的底层实现是array,封装后使用更友好。 91 | 92 | 双指针法(快慢指针法)在数组和链表的操作中是非常常见的,很多考察数组和链表操作的面试题,都使用双指针法。 93 | 94 | ## 滑动窗口 95 | 96 | * [数组:滑动窗口拯救了你](https://programmercarl.com/0209.长度最小的子数组.html) 97 | 98 | 本题介绍了数组操作中的另一个重要思想:滑动窗口。 99 | 100 | * 暴力解法时间复杂度:$O(n^2)$ 101 | * 滑动窗口时间复杂度:$O(n)$ 102 | 103 | 本题中,主要要理解滑动窗口如何移动 窗口起始位置,达到动态更新窗口大小的,从而得出长度最小的符合条件的长度。 104 | 105 | **滑动窗口的精妙之处在于根据当前子序列和大小的情况,不断调节子序列的起始位置。从而将$O(n^2)$的暴力解法降为$O(n)$。** 106 | 107 | 如果没有接触过这一类的方法,很难想到类似的解题思路,滑动窗口方法还是很巧妙的。 108 | 109 | 110 | ## 模拟行为 111 | 112 | * [数组:这个循环可以转懵很多人!](https://programmercarl.com/0059.螺旋矩阵II.html) 113 | 114 | 模拟类的题目在数组中很常见,不涉及到什么算法,就是单纯的模拟,十分考察大家对代码的掌控能力。 115 | 116 | 在这道题目中,我们再一次介绍到了**循环不变量原则**,其实这也是写程序中的重要原则。 117 | 118 | 相信大家又遇到过这种情况: 感觉题目的边界调节超多,一波接着一波的判断,找边界,踩了东墙补西墙,好不容易运行通过了,代码写的十分冗余,毫无章法,其实**真正解决题目的代码都是简洁的,或者有原则性的**,大家可以在这道题目中体会到这一点。 119 | 120 | 121 | # 总结 122 | 123 | 从二分法到双指针,从滑动窗口到螺旋矩阵,相信如果大家真的认真做了「代码随想录」每日推荐的题目,定会有所收获。 124 | 125 | 推荐的题目即使大家之前做过了,再读一遍文章,也会帮助你提炼出解题的精髓所在。 126 | 127 | 如果感觉有所收获,希望大家多多支持,打卡转发,点赞在看 都是对我最大的鼓励! 128 | 129 | 最后,大家周末愉快! 130 | 131 | 132 | ----------------------- 133 |
134 | -------------------------------------------------------------------------------- /problems/0283.移动零.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 |

参与本项目,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!

6 | 7 | # 动态规划:一样的套路,再求一次完全平方数 8 | 9 | # 283. 移动零 10 | 11 | [力扣题目链接](https://leetcode-cn.com/problems/move-zeroes/) 12 | 13 | 给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。 14 | 15 | 示例: 16 | 17 | 输入: [0,1,0,3,12] 18 | 输出: [1,3,12,0,0] 19 | 说明: 20 | 21 | 必须在原数组上操作,不能拷贝额外的数组。 22 | 尽量减少操作次数。 23 | 24 | 25 | # 思路 26 | 27 | 做这道题目之前,大家可以做一做[27.移除元素](https://programmercarl.com/0027.移除元素.html) 28 | 29 | 这道题目,使用暴力的解法,可以两层for循环,模拟数组删除元素(也就是向前覆盖)的过程。 30 | 31 | 好了,我们说一说双指针法,大家如果对双指针还不熟悉,可以看我的这篇总结[双指针法:总结篇!](https://programmercarl.com/双指针总结.html)。 32 | 33 | 双指针法在数组移除元素中,可以达到$O(n)$的时间复杂度,在[27.移除元素](https://programmercarl.com/0027.移除元素.html)里已经详细讲解了,那么本题和移除元素其实是一个套路。 34 | 35 | **相当于对整个数组移除元素0,然后slowIndex之后都是移除元素0的冗余元素,把这些元素都赋值为0就可以了**。 36 | 37 | 如动画所示: 38 | 39 | ![移动零](https://tva1.sinaimg.cn/large/e6c9d24ely1gojdlrvqqig20jc0dakjn.gif) 40 | 41 | C++代码如下: 42 | 43 | ```CPP 44 | class Solution { 45 | public: 46 | void moveZeroes(vector& nums) { 47 | int slowIndex = 0; 48 | for (int fastIndex = 0; fastIndex < nums.size(); fastIndex++) { 49 | if (nums[fastIndex] != 0) { 50 | nums[slowIndex++] = nums[fastIndex]; 51 | } 52 | } 53 | // 将slowIndex之后的冗余元素赋值为0 54 | for (int i = slowIndex; i < nums.size(); i++) { 55 | nums[i] = 0; 56 | } 57 | } 58 | }; 59 | ``` 60 | 61 | # 其他语言版本 62 | 63 | Java: 64 | 65 | ```java 66 | public void moveZeroes(int[] nums) { 67 | int slow = 0; 68 | for (int fast = 0; fast < nums.length; fast++) { 69 | if (nums[fast] != 0) { 70 | nums[slow++] = nums[fast]; 71 | } 72 | } 73 | // 后面的元素全变成 0 74 | for (int j = slow; j < nums.length; j++) { 75 | nums[j] = 0; 76 | } 77 | } 78 | ``` 79 | 80 | Python: 81 | 82 | ```python 83 | def moveZeroes(self, nums: List[int]) -> None: 84 | slow = 0 85 | for fast in range(len(nums)): 86 | if nums[fast] != 0: 87 | nums[slow] = nums[fast] 88 | slow += 1 89 | for i in range(slow, len(nums)): 90 | nums[i] = 0 91 | ``` 92 | 交换前后变量,避免补零 93 | ```python 94 | def moveZeroes(self, nums: List[int]) -> None: 95 | slow, fast = 0, 0 96 | while fast < len(nums): 97 | if nums[fast] != 0: 98 | nums[slow], nums[fast] = nums[fast], nums[slow] 99 | slow += 1 # 保持[0, slow)区间是没有0的 100 | fast += 1 101 | ``` 102 | 103 | Go: 104 | 105 | ```go 106 | func moveZeroes(nums []int) { 107 | slow := 0 108 | for fast := 0; fast < len(nums); fast ++ { 109 | if nums[fast] != 0 { 110 | temp := nums[slow] 111 | nums[slow] = nums[fast] 112 | nums[fast] = temp 113 | slow++ 114 | } 115 | } 116 | } 117 | ``` 118 | 119 | JavaScript: 120 | ```javascript 121 | var moveZeroes = function(nums) { 122 | let slow = 0; 123 | for(let fast = 0; fast < nums.length; fast++){ 124 | if(nums[fast] != 0){//找到非0的元素 125 | nums[slow] = nums[fast];//把非0的元素赋值给数组慢指针指向的索引处的值 126 | slow++;//慢指针向右移动 127 | } 128 | } 129 | // 后面的元素全变成 0 130 | for(let j = slow; j < nums.length; j++){ 131 | nums[j] = 0; 132 | } 133 | }; 134 | ``` 135 | 136 | 137 | ----------------------- 138 |
139 | -------------------------------------------------------------------------------- /problems/0189.旋转数组.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 |

参与本项目,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!

6 | 7 | 8 | # 189. 旋转数组 9 | 10 | 给定一个数组,将数组中的元素向右移动 k 个位置,其中 k 是非负数。 11 | 12 | 进阶: 13 | 14 | 尽可能想出更多的解决方案,至少有三种不同的方法可以解决这个问题。 15 | 你可以使用空间复杂度为 $O(1)$ 的 原地 算法解决这个问题吗? 16 | 17 | 示例 1: 18 | 19 | * 输入: nums = [1,2,3,4,5,6,7], k = 3 20 | * 输出: [5,6,7,1,2,3,4] 21 | * 解释: 22 | 向右旋转 1 步: [7,1,2,3,4,5,6]。 23 | 向右旋转 2 步: [6,7,1,2,3,4,5]。 24 | 向右旋转 3 步: [5,6,7,1,2,3,4]。 25 | 26 | 示例 2: 27 | * 输入:nums = [-1,-100,3,99], k = 2 28 | * 输出:[3,99,-1,-100] 29 | * 解释: 30 | 向右旋转 1 步: [99,-1,-100,3]。 31 | 向右旋转 2 步: [3,99,-1,-100]。 32 | 33 | 34 | # 思路 35 | 36 | 这道题目在字符串里其实很常见,我把字符串反转相关的题目列一下: 37 | 38 | * [字符串:力扣541.反转字符串II](https://programmercarl.com/0541.反转字符串II.html) 39 | * [字符串:力扣151.翻转字符串里的单词](https://programmercarl.com/0151.翻转字符串里的单词.html) 40 | * [字符串:剑指Offer58-II.左旋转字符串](https://programmercarl.com/剑指Offer58-II.左旋转字符串.html) 41 | 42 | 本题其实和[字符串:剑指Offer58-II.左旋转字符串](https://programmercarl.com/剑指Offer58-II.左旋转字符串.html)就非常像了,剑指offer上左旋转,本题是右旋转。 43 | 44 | 注意题目要求是**要求使用空间复杂度为 $O(1)$ 的 原地 算法** 45 | 46 | 那么我来提供一种旋转的方式哈。 47 | 48 | 在[字符串:剑指Offer58-II.左旋转字符串](https://programmercarl.com/剑指Offer58-II.左旋转字符串.html)中,我们提到,如下步骤就可以坐旋转字符串: 49 | 50 | 1. 反转区间为前n的子串 51 | 2. 反转区间为n到末尾的子串 52 | 3. 反转整个字符串 53 | 54 | 本题是右旋转,其实就是反转的顺序改动一下,优先反转整个字符串,步骤如下: 55 | 56 | 1. 反转整个字符串 57 | 2. 反转区间为前k的子串 58 | 3. 反转区间为k到末尾的子串 59 | 60 | **需要注意的是,本题还有一个小陷阱,题目输入中,如果k大于nums.size了应该怎么办?** 61 | 62 | 举个例子,比较容易想, 63 | 64 | 例如,1,2,3,4,5,6,7 如果右移动15次的话,是 7 1 2 3 4 5 6 。 65 | 66 | 所以其实就是右移 k % nums.size() 次,即:15 % 7 = 1 67 | 68 | C++代码如下: 69 | 70 | ```CPP 71 | class Solution { 72 | public: 73 | void rotate(vector& nums, int k) { 74 | k = k % nums.size(); 75 | reverse(nums.begin(), nums.end()); 76 | reverse(nums.begin(), nums.begin() + k); 77 | reverse(nums.begin() + k, nums.end()); 78 | 79 | } 80 | }; 81 | ``` 82 | 83 | 84 | # 其他语言版本 85 | 86 | ## Java 87 | 88 | ```java 89 | class Solution { 90 | private void reverse(int[] nums, int start, int end) { 91 | for (int i = start, j = end; i < j; i++, j--) { 92 | int temp = nums[j]; 93 | nums[j] = nums[i]; 94 | nums[i] = temp; 95 | } 96 | } 97 | public void rotate(int[] nums, int k) { 98 | int n = nums.length; 99 | k %= n; 100 | reverse(nums, 0, n - 1); 101 | reverse(nums, 0, k - 1); 102 | reverse(nums, k, n - 1); 103 | } 104 | } 105 | ``` 106 | 107 | ## Python 108 | 109 | ```python 110 | class Solution: 111 | def rotate(self, A: List[int], k: int) -> None: 112 | def reverse(i, j): 113 | while i < j: 114 | A[i], A[j] = A[j], A[i] 115 | i += 1 116 | j -= 1 117 | n = len(A) 118 | k %= n 119 | reverse(0, n - 1) 120 | reverse(0, k - 1) 121 | reverse(k, n - 1) 122 | ``` 123 | 124 | ## Go 125 | 126 | ```go 127 | ``` 128 | 129 | ## JavaScript 130 | 131 | ```js 132 | var rotate = function (nums, k) { 133 | function reverse(nums, i, j) { 134 | while (i < j) { 135 | [nums[i],nums[j]] = [nums[j],nums[i]]; // 解构赋值 136 | i++; 137 | j--; 138 | } 139 | } 140 | let n = nums.length; 141 | k %= n; 142 | if (k) { 143 | reverse(nums, 0, n - 1); 144 | reverse(nums, 0, k - 1); 145 | reverse(nums, k, n - 1); 146 | } 147 | }; 148 | ``` 149 | 150 | 151 | 152 | ----------------------- 153 |
154 | -------------------------------------------------------------------------------- /problems/周总结/20201030回溯周末总结.md: -------------------------------------------------------------------------------- 1 | 2 | 3 |

4 | 5 | 6 | 7 | 8 |

9 | 10 | -------------------------- 11 | 12 | ## 周一 13 | 14 | 本周我们正式开始了回溯算法系列,那么首先当然是概述。 15 | 16 | 在[关于回溯算法,你该了解这些!](https://programmercarl.com/回溯算法理论基础.html)中介绍了什么是回溯,回溯法的效率,回溯法解决的问题以及回溯法模板。 17 | 18 | **回溯是递归的副产品,只要有递归就会有回溯**。 19 | 20 | 回溯法就是暴力搜索,并不是什么高效的算法,最多在剪枝一下。 21 | 22 | 回溯算法能解决如下问题: 23 | 24 | * 组合问题:N个数里面按一定规则找出k个数的集合 25 | * 排列问题:N个数按一定规则全排列,有几种排列方式 26 | * 切割问题:一个字符串按一定规则有几种切割方式 27 | * 子集问题:一个N个数的集合里有多少符合条件的子集 28 | * 棋盘问题:N皇后,解数独等等 29 | 30 | 是不是感觉回溯算法有点厉害了。 31 | 32 | 回溯法确实不好理解,所以需要把回溯法抽象为一个图形来理解就容易多了,每一道回溯法的题目都可以抽象为树形结构。 33 | 34 | 针对很多同学都写不好回溯,我在[关于回溯算法,你该了解这些!](https://programmercarl.com/回溯算法理论基础.html)用回溯三部曲,分析了回溯算法,并给出了回溯法的模板。 35 | 36 | 这个模板会伴随整个回溯法系列! 37 | 38 | ## 周二 39 | 40 | 41 | 在[回溯算法:求组合问题!](https://programmercarl.com/0077.组合.html)中,我们开始用回溯法解决第一道题目,组合问题。 42 | 43 | 我在文中开始的时候给大家列举k层for循环例子,进而得出都是同样是暴力解法,为什么要用回溯法。 44 | 45 | **此时大家应该深有体会回溯法的魅力,用递归控制for循环嵌套的数量!** 46 | 47 | 本题我把回溯问题抽象为树形结构,可以直观的看出其搜索的过程:**for循环横向遍历,递归纵向遍历,回溯不断调整结果集**。 48 | 49 | ## 周三 50 | 51 | 针对[回溯算法:求组合问题!](https://programmercarl.com/0077.组合.html)还可以做剪枝的操作。 52 | 53 | 在[回溯算法:组合问题再剪剪枝](https://programmercarl.com/0077.组合优化.html)中把回溯法代码做了剪枝优化,在文中我依然把问题抽象为一个树形结构,大家可以一目了然剪的究竟是哪里。 54 | 55 | **剪枝精髓是:for循环在寻找起点的时候要有一个范围,如果这个起点到集合终止之间的元素已经不够 题目要求的k个元素了,就没有必要搜索了**。 56 | 57 | ## 周四 58 | 59 | 在[回溯算法:求组合总和!](https://programmercarl.com/0216.组合总和III.html)中,相当于 [回溯算法:求组合问题!](https://programmercarl.com/0077.组合.html)加了一个元素总和的限制。 60 | 61 | 整体思路还是一样的,本题的剪枝会好想一些,即:**已选元素总和如果已经大于n(题中要求的和)了,那么往后遍历就没有意义了,直接剪掉**。 62 | 63 | 在本题中,依然还可以有一个剪枝,就是[回溯算法:组合问题再剪剪枝](https://programmercarl.com/0077.组合优化.html)中提到的,对for循环选择的起始范围的剪枝。 64 | 65 | 所以,剪枝的代码,可以把for循环,加上 `i <= 9 - (k - path.size()) + 1` 的限制! 66 | 67 | 组合总和问题还有一些花样,下周还会介绍到。 68 | 69 | ## 周五 70 | 71 | 在[回溯算法:电话号码的字母组合](https://programmercarl.com/0017.电话号码的字母组合.html)中,开始用多个集合来求组合,还是熟悉的模板题目,但是有一些细节。 72 | 73 | 例如这里for循环,可不像是在 [回溯算法:求组合问题!](https://programmercarl.com/0077.组合.html)和[回溯算法:求组合总和!](https://programmercarl.com/0216.组合总和III.html)中从startIndex开始遍历的。 74 | 75 | **因为本题每一个数字代表的是不同集合,也就是求不同集合之间的组合,而[回溯算法:求组合问题!](https://programmercarl.com/0077.组合.html)和[回溯算法:求组合总和!](https://programmercarl.com/0216.组合总和III.html)都是是求同一个集合中的组合!** 76 | 77 | 如果大家在现场面试的时候,一定要注意各种输入异常的情况,例如本题输入1 * #按键。 78 | 79 | 其实本题不算难,但也处处是细节,还是要反复琢磨。 80 | 81 | ## 周六 82 | 83 | 因为之前链表系列没有写总结,虽然链表系列已经是两个月前的事情,但还是有必要补一下。 84 | 85 | 所以给出[链表:总结篇!](https://programmercarl.com/链表总结篇.html),这里对之前链表理论基础和经典题目进行了总结。 86 | 87 | 同时对[链表:环找到了,那入口呢?](https://programmercarl.com/0142.环形链表II.html)中求环入口的问题又进行了补充证明,可以说把环形链表的方方面面都讲的很通透了,大家如果没有做过环形链表的题目一定要去做一做。 88 | 89 | ## 总结 90 | 91 | 相信通过这一周对回溯法的学习,大家已经掌握其题本套路了,也不会对回溯法那么畏惧了。 92 | 93 | 回溯法抽象为树形结构后,其遍历过程就是:**for循环横向遍历,递归纵向遍历,回溯不断调整结果集**。 94 | 95 | 这个是我做了很多回溯的题目,不断摸索其规律才总结出来的。 96 | 97 | 对于回溯法的整体框架,网上搜的文章这块一般都说不清楚,按照天上掉下来的代码对着讲解,不知道究竟是怎么来的,也不知道为什么要这么写。 98 | 99 | 所以,录友们刚开始学回溯法,起跑姿势就很标准了,哈哈。 100 | 101 | 下周依然是回溯法,难度又要上升一个台阶了。 102 | 103 | 最后祝录友们周末愉快! 104 | 105 | **如果感觉「代码随想录」不错,就分享给身边的同学朋友吧,一起来学习算法!** 106 | 107 | 108 | 109 | ------------------------ 110 | 111 | * 微信:[程序员Carl](https://mp.weixin.qq.com/s/b66DFkOp8OOxdZC_xLZxfw) 112 | * B站:[代码随想录](https://space.bilibili.com/525438321) 113 | * 知识星球:[代码随想录](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ) 114 | 115 |
116 | -------------------------------------------------------------------------------- /problems/字符串总结.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 |

参与本项目,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!

6 | 7 | 8 | # 字符串:总结篇 9 | 10 | 其实我们已经学习了十天的字符串了,从字符串的定义到库函数的使用原则,从各种反转到KMP算法,相信大家应该对字符串有比较深刻的认识了。 11 | 12 | 那么这次我们来做一个总结。 13 | 14 | # 什么是字符串 15 | 16 | 字符串是若干字符组成的有限序列,也可以理解为是一个字符数组,但是很多语言对字符串做了特殊的规定,接下来我来说一说C/C++中的字符串。 17 | 18 | 在C语言中,把一个字符串存入一个数组时,也把结束符 '\0'存入数组,并以此作为该字符串是否结束的标志。 19 | 20 | 例如这段代码: 21 | 22 | ``` 23 | char a[5] = "asd"; 24 | for (int i = 0; a[i] != '\0'; i++) { 25 | } 26 | ``` 27 | 28 | 在C++中,提供一个string类,string类会提供 size接口,可以用来判断string类字符串是否结束,就不用'\0'来判断是否结束。 29 | 30 | 例如这段代码: 31 | 32 | ``` 33 | string a = "asd"; 34 | for (int i = 0; i < a.size(); i++) { 35 | } 36 | ``` 37 | 38 | 那么vector< char > 和 string 又有什么区别呢? 39 | 40 | 其实在基本操作上没有区别,但是 string提供更多的字符串处理的相关接口,例如string 重载了+,而vector却没有。 41 | 42 | 所以想处理字符串,我们还是会定义一个string类型。 43 | 44 | 45 | # 要不要使用库函数 46 | 47 | 在文章[344.反转字符串](https://programmercarl.com/0344.反转字符串.html)中强调了**打基础的时候,不要太迷恋于库函数。** 48 | 49 | 甚至一些同学习惯于调用substr,split,reverse之类的库函数,却不知道其实现原理,也不知道其时间复杂度,这样实现出来的代码,如果在面试现场,面试官问:“分析其时间复杂度”的话,一定会一脸懵逼! 50 | 51 | 所以建议**如果题目关键的部分直接用库函数就可以解决,建议不要使用库函数。** 52 | 53 | **如果库函数仅仅是 解题过程中的一小部分,并且你已经很清楚这个库函数的内部实现原理的话,可以考虑使用库函数。** 54 | 55 | # 双指针法 56 | 57 | 58 | 在[344.反转字符串](https://programmercarl.com/0344.反转字符串.html) ,我们使用双指针法实现了反转字符串的操作,**双指针法在数组,链表和字符串中很常用。** 59 | 60 | 接着在[字符串:替换空格](https://programmercarl.com/剑指Offer05.替换空格.html),同样还是使用双指针法在时间复杂度$O(n)$的情况下完成替换空格。 61 | 62 | **其实很多数组填充类的问题,都可以先预先给数组扩容带填充后的大小,然后在从后向前进行操作。** 63 | 64 | 那么针对数组删除操作的问题,其实在[27. 移除元素](https://programmercarl.com/0027.移除元素.html)中就已经提到了使用双指针法进行移除操作。 65 | 66 | 同样的道理在[151.翻转字符串里的单词](https://programmercarl.com/0151.翻转字符串里的单词.html)中我们使用$O(n)$的时间复杂度,完成了删除冗余空格。 67 | 68 | 一些同学会使用for循环里调用库函数erase来移除元素,这其实是$O(n^2)$的操作,因为erase就是$O(n)$的操作,所以这也是典型的不知道库函数的时间复杂度,上来就用的案例了。 69 | 70 | # 反转系列 71 | 72 | 在反转上还可以在加一些玩法,其实考察的是对代码的掌控能力。 73 | 74 | [541. 反转字符串II](https://programmercarl.com/0541.反转字符串II.html)中,一些同学可能为了处理逻辑:每隔2k个字符的前k的字符,写了一堆逻辑代码或者再搞一个计数器,来统计2k,再统计前k个字符。 75 | 76 | 其实**当需要固定规律一段一段去处理字符串的时候,要想想在在for循环的表达式上做做文章**。 77 | 78 | 只要让 i += (2 * k),i 每次移动 2 * k 就可以了,然后判断是否需要有反转的区间。 79 | 80 | 因为要找的也就是每2 * k 区间的起点,这样写程序会高效很多。 81 | 82 | 在[151.翻转字符串里的单词](https://programmercarl.com/0151.翻转字符串里的单词.html)中要求翻转字符串里的单词,这道题目可以说是综合考察了字符串的多种操作。是考察字符串的好题。 83 | 84 | 这道题目通过 **先整体反转再局部反转**,实现了反转字符串里的单词。 85 | 86 | 后来发现反转字符串还有一个牛逼的用处,就是达到左旋的效果。 87 | 88 | 在[字符串:反转个字符串还有这个用处?](https://programmercarl.com/剑指Offer58-II.左旋转字符串.html)中,我们通过**先局部反转再整体反转**达到了左旋的效果。 89 | 90 | # KMP 91 | 92 | KMP的主要思想是**当出现字符串不匹配时,可以知道一部分之前已经匹配的文本内容,可以利用这些信息避免从头再去做匹配了。** 93 | 94 | KMP的精髓所在就是前缀表,在[KMP精讲](https://programmercarl.com/0028.实现strStr.html)中提到了,什么是KMP,什么是前缀表,以及为什么要用前缀表。 95 | 96 | 前缀表:起始位置到下标i之前(包括i)的子串中,有多大长度的相同前缀后缀。 97 | 98 | 那么使用KMP可以解决两类经典问题: 99 | 100 | 1. 匹配问题:[28. 实现 strStr()](https://programmercarl.com/0028.实现strStr.html) 101 | 2. 重复子串问题:[459.重复的子字符串](https://programmercarl.com/0459.重复的子字符串.html) 102 | 103 | 再一次强调了什么是前缀,什么是后缀,什么又是最长相等前后缀。 104 | 105 | 前缀:指不包含最后一个字符的所有以第一个字符开头的连续子串。 106 | 107 | 后缀:指不包含第一个字符的所有以最后一个字符结尾的连续子串。 108 | 109 | 然后**针对前缀表到底要不要减一,这其实是不同KMP实现的方式**,我们在[KMP精讲](https://programmercarl.com/0028.实现strStr.html)中针对之前两个问题,分别给出了两个不同版本的的KMP实现。 110 | 111 | 其中主要**理解j=next[x]这一步最为关键!** 112 | 113 | # 总结 114 | 115 | 字符串类类型的题目,往往想法比较简单,但是实现起来并不容易,复杂的字符串题目非常考验对代码的掌控能力。 116 | 117 | 双指针法是字符串处理的常客。 118 | 119 | KMP算法是字符串查找最重要的算法,但彻底理解KMP并不容易,我们已经写了五篇KMP的文章,不断总结和完善,最终才把KMP讲清楚。 120 | 121 | 好了字符串相关的算法知识就介绍到了这里了,明天开始新的征程,大家加油! 122 | 123 | 124 | 125 | 126 | 127 | ----------------------- 128 |
129 | -------------------------------------------------------------------------------- /problems/0724.寻找数组的中心索引.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 |

参与本项目,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!

6 | 7 | 8 | # 724.寻找数组的中心下标 9 | 10 | [力扣题目链接](https://leetcode-cn.com/problems/find-pivot-index/) 11 | 12 | 给你一个整数数组 nums ,请计算数组的 中心下标 。 13 | 14 | 数组 中心下标 是数组的一个下标,其左侧所有元素相加的和等于右侧所有元素相加的和。 15 | 16 | 如果中心下标位于数组最左端,那么左侧数之和视为 0 ,因为在下标的左侧不存在元素。这一点对于中心下标位于数组最右端同样适用。 17 | 18 | 如果数组有多个中心下标,应该返回 最靠近左边 的那一个。如果数组不存在中心下标,返回 -1 。 19 | 20 | 示例 1: 21 | * 输入:nums = [1, 7, 3, 6, 5, 6] 22 | * 输出:3 23 | * 解释:中心下标是 3。左侧数之和 sum = nums[0] + nums[1] + nums[2] = 1 + 7 + 3 = 11 ,右侧数之和 sum = nums[4] + nums[5] = 5 + 6 = 11 ,二者相等。 24 | 25 | 示例 2: 26 | * 输入:nums = [1, 2, 3] 27 | * 输出:-1 28 | * 解释:数组中不存在满足此条件的中心下标。 29 | 30 | 示例 3: 31 | * 输入:nums = [2, 1, -1] 32 | * 输出:0 33 | * 解释:中心下标是 0。左侧数之和 sum = 0 ,(下标 0 左侧不存在元素),右侧数之和 sum = nums[1] + nums[2] = 1 + -1 = 0 。 34 | 35 | 36 | ## 思路 37 | 38 | 这道题目还是比较简单直接的 39 | 40 | 1. 遍历一遍求出总和sum 41 | 2. 遍历第二遍求中心索引左半和leftSum 42 | * 同时根据sum和leftSum 计算中心索引右半和rightSum 43 | * 判断leftSum和rightSum是否相同 44 | 45 | C++代码如下: 46 | ```CPP 47 | class Solution { 48 | public: 49 | int pivotIndex(vector& nums) { 50 | int sum = 0; 51 | for (int num : nums) sum += num; // 求和 52 | int leftSum = 0; // 中心索引左半和 53 | int rightSum = 0; // 中心索引右半和 54 | for (int i = 0; i < nums.size(); i++) { 55 | leftSum += nums[i]; 56 | rightSum = sum - leftSum + nums[i]; 57 | if (leftSum == rightSum) return i; 58 | } 59 | return -1; 60 | } 61 | }; 62 | ``` 63 | 64 | 65 | ## 其他语言版本 66 | 67 | ### Java 68 | 69 | ```java 70 | class Solution { 71 | public int pivotIndex(int[] nums) { 72 | int sum = 0; 73 | for (int i = 0; i < nums.length; i++) { 74 | sum += nums[i]; // 总和 75 | } 76 | int leftSum = 0; 77 | int rightSum = 0; 78 | for (int i = 0; i < nums.length; i++) { 79 | leftSum += nums[i]; 80 | rightSum = sum - leftSum + nums[i]; // leftSum 里面已经有 nums[i],多减了一次,所以加上 81 | if (leftSum == rightSum) { 82 | return i; 83 | } 84 | } 85 | return -1; // 不存在 86 | } 87 | } 88 | ``` 89 | 90 | ### Python3 91 | 92 | ```python 93 | class Solution: 94 | def pivotIndex(self, nums: List[int]) -> int: 95 | numSum = sum(nums) #数组总和 96 | leftSum = 0 97 | for i in range(len(nums)): 98 | if numSum - leftSum -nums[i] == leftSum: #左右和相等 99 | return i 100 | leftSum += nums[i] 101 | return -1 102 | ``` 103 | 104 | ### Go 105 | 106 | ```go 107 | func pivotIndex(nums []int) int { 108 | sum := 0 109 | for _, v := range nums { 110 | sum += v; 111 | } 112 | 113 | leftSum := 0 // 中心索引左半和 114 | rightSum := 0 // 中心索引右半和 115 | for i := 0; i < len(nums); i++ { 116 | leftSum += nums[i] 117 | rightSum = sum - leftSum + nums[i] 118 | if leftSum == rightSum{ 119 | return i 120 | } 121 | } 122 | return -1 123 | } 124 | 125 | ``` 126 | 127 | ### JavaScript 128 | 129 | ```js 130 | var pivotIndex = function(nums) { 131 | const sum = nums.reduce((a,b) => a + b);//求和 132 | // 中心索引左半和 中心索引右半和 133 | let leftSum = 0, rightSum = 0; 134 | for(let i = 0; i < nums.length; i++){ 135 | leftSum += nums[i]; 136 | rightSum = sum - leftSum + nums[i];// leftSum 里面已经有 nums[i],多减了一次,所以加上 137 | if(leftSum === rightSum) return i; 138 | } 139 | return -1; 140 | }; 141 | ``` 142 | 143 | 144 | ----------------------- 145 |
146 | -------------------------------------------------------------------------------- /problems/周总结/20210107动规周末总结.md: -------------------------------------------------------------------------------- 1 | 2 | 这周我们正式开始动态规划的学习! 3 | 4 | ## 周一 5 | 6 | 在[关于动态规划,你该了解这些!](https://programmercarl.com/动态规划理论基础.html)中我们讲解了动态规划的基础知识。 7 | 8 | 首先讲一下动规和贪心的区别,其实大家不用太强调理论上的区别,做做题,就感受出来了。 9 | 10 | 然后我们讲了动规的五部曲: 11 | 12 | 1. 确定dp数组(dp table)以及下标的含义 13 | 2. 确定递推公式 14 | 3. dp数组如何初始化 15 | 4. 确定遍历顺序 16 | 5. 举例推导dp数组 17 | 18 | 后序我们在讲解动规的题目时候,都离不开这五步! 19 | 20 | 本周都是简单题目,大家可能会感觉 按照这五部来好麻烦,凭感觉随手一写,直接就过,越到后面越会感觉,凭感觉这个事还是不靠谱的,哈哈。 21 | 22 | 最后我们讲了动态规划题目应该如何debug,相信一些录友做动规的题目,一旦报错也是凭感觉来改。 23 | 24 | 其实只要把dp数组打印出来,哪里有问题一目了然! 25 | 26 | **如果代码写出来了,一直AC不了,灵魂三问:** 27 | 28 | 1. 这道题目我举例推导状态转移公式了么? 29 | 2. 我打印dp数组的日志了么? 30 | 3. 打印出来了dp数组和我想的一样么? 31 | 32 | 哈哈,专治各种代码写出来了但AC不了的疑难杂症。 33 | 34 | ## 周二 35 | 36 | 这道题目[动态规划:斐波那契数](https://programmercarl.com/0509.斐波那契数.html)是当之无愧的动规入门题。 37 | 38 | 简单题,我们就是用来了解方法论的,用动规五部曲走一遍,题目其实已经把递推公式,和dp数组如何初始化都给我们了。 39 | 40 | ## 周三 41 | 42 | [动态规划:爬楼梯](https://programmercarl.com/0070.爬楼梯.html) 这道题目其实就是斐波那契数列。 43 | 44 | 但正常思考过程应该是推导完递推公式之后,发现这是斐波那契,而不是上来就知道这是斐波那契。 45 | 46 | 在这道题目的第三步,确认dp数组如何初始化,其实就可以看出来,对dp[i]定义理解的深度。 47 | 48 | dp[0]其实就是一个无意义的存在,不用去初始化dp[0]。 49 | 50 | 有的题解是把dp[0]初始化为1,然后遍历的时候i从2开始遍历,这样是可以解题的,然后强行解释一波dp[0]应该等于1的含义。 51 | 52 | 一个严谨的思考过程,应该是初始化dp[1] = 1,dp[2] = 2,然后i从3开始遍历,代码如下: 53 | 54 | ```CPP 55 | dp[1] = 1; 56 | dp[2] = 2; 57 | for (int i = 3; i <= n; i++) { // 注意i是从3开始的 58 | dp[i] = dp[i - 1] + dp[i - 2]; 59 | } 60 | ``` 61 | 62 | 这个可以是面试的一个小问题,哈哈,考察候选人对dp[i]定义的理解程度。 63 | 64 | 这道题目还可以继续深化,就是一步一个台阶,两个台阶,三个台阶,直到 m个台阶,有多少种方法爬到n阶楼顶。 65 | 66 | 这又有难度了,这其实是一个完全背包问题,但力扣上没有这种题目,所以后续我在讲解背包问题的时候,今天这道题还会拿从背包问题的角度上来再讲一遍。 67 | 68 | 这里我先给出我的实现代码: 69 | 70 | ```CPP 71 | class Solution { 72 | public: 73 | int climbStairs(int n) { 74 | vector dp(n + 1, 0); 75 | dp[0] = 1; 76 | for (int i = 1; i <= n; i++) { 77 | for (int j = 1; j <= m; j++) { // 把m换成2,就可以AC爬楼梯这道题 78 | if (i - j >= 0) dp[i] += dp[i - j]; 79 | } 80 | } 81 | return dp[n]; 82 | } 83 | }; 84 | ``` 85 | 86 | 代码中m表示最多可以爬m个台阶。 87 | 88 | **以上代码不能运行哈,我主要是为了体现只要把m换成2,粘过去,就可以AC爬楼梯这道题,不信你就粘一下试试,哈哈**。 89 | 90 | 91 | **此时我就发现一个绝佳的大厂面试题**,第一道题就是单纯的爬楼梯,然后看候选人的代码实现,如果把dp[0]的定义成1了,就可以发难了,为什么dp[0]一定要初始化为1,此时可能候选人就要强行给dp[0]应该是1找各种理由。那这就是一个考察点了,对dp[i]的定义理解的不深入。 92 | 93 | 然后可以继续发难,如果一步一个台阶,两个台阶,三个台阶,直到 m个台阶,有多少种方法爬到n阶楼顶。这道题目leetcode上并没有原题,绝对是考察候选人算法能力的绝佳好题。 94 | 95 | 这一连套问下来,候选人算法能力如何,面试官心里就有数了。 96 | 97 | **其实大厂面试最喜欢问题的就是这种简单题,然后慢慢变化,在小细节上考察候选人**。 98 | 99 | 这道绝佳的面试题我没有用过,如果录友们有面试别人的需求,就把这个套路拿去吧,哈哈哈。 100 | 101 | 我在[通过一道面试题目,讲一讲递归算法的时间复杂度!](https://programmercarl.com/前序/通过一道面试题目,讲一讲递归算法的时间复杂度!.html)中,以我自己面试别人的真实经历,通过求x的n次方 这么简单的题目,就可以考察候选人对算法性能以及递归的理解深度,录友们可以看看,绝对有收获! 102 | 103 | ## 周四 104 | 105 | 这道题目[动态规划:使用最小花费爬楼梯](https://programmercarl.com/0746.使用最小花费爬楼梯.html)就是在爬台阶的基础上加了一个花费, 106 | 107 | 这道题描述也确实有点魔幻。 108 | 109 | 题目描述为:每当你爬上一个阶梯你都要花费对应的体力值,一旦支付了相应的体力值,你就可以选择向上爬一个阶梯或者爬两个阶梯。 110 | 111 | 示例1: 112 | 113 | 输入:cost = [10, 15, 20] 114 | 输出:15 115 | 116 | 117 | **从题目描述可以看出:要不是第一步不需要花费体力,要不就是第最后一步不需要花费体力,我个人理解:题意说的其实是第一步是要支付费用的!**。因为是当你爬上一个台阶就要花费对应的体力值! 118 | 119 | 所以我定义的dp[i]意思是也是第一步是要花费体力的,最后一步不用花费体力了,因为已经支付了。 120 | 121 | 之后一些录友在留言区说 可以定义dp[i]为:第一步是不花费体力,最后一步是花费体力的。 122 | 123 | 所以代码也可以这么写: 124 | 125 | ```CPP 126 | class Solution { 127 | public: 128 | int minCostClimbingStairs(vector& cost) { 129 | vector dp(cost.size() + 1); 130 | dp[0] = 0; // 默认第一步都是不花费体力的 131 | dp[1] = 0; 132 | for (int i = 2; i <= cost.size(); i++) { 133 | dp[i] = min(dp[i - 1] + cost[i - 1], dp[i - 2] + cost[i - 2]); 134 | } 135 | return dp[cost.size()]; 136 | } 137 | }; 138 | ``` 139 | 140 | 这么写看上去比较顺,但是就是感觉和题目描述的不太符。哈哈,也没有必要这么细扣题意了,大家只要知道,题目的意思反正就是要不是第一步不花费,要不是最后一步不花费,都可以。 141 | 142 | ## 总结 143 | 144 | 本周题目简单一些,也非常合适初学者来练练手。 145 | 146 | 下周开始上难度了哈,然后大下周就开始讲解背包问题,好戏还在后面,录友们跟上哈。 147 | 148 | 学算法,认准「代码随想录」就够了,Carl带你打怪升级! 149 | 150 | 151 | 152 |
153 | -------------------------------------------------------------------------------- /problems/周总结/20210121动规周末总结.md: -------------------------------------------------------------------------------- 1 | # 本周小结!(动态规划系列三) 2 | 本周我们正式开始讲解背包问题,也是动规里非常重要的一类问题。 3 | 4 | 背包问题其实有很多细节,如果了解个大概,然后也能一气呵成把代码写出来,但稍稍变变花样可能会陷入迷茫了。 5 | 6 | 开始回顾一下本周的内容吧! 7 | 8 | ## 周一 9 | 10 | [动态规划:关于01背包问题,你该了解这些!](https://programmercarl.com/背包理论基础01背包-1.html)中,我们开始介绍了背包问题。 11 | 12 | 首先对于背包的所有问题中,01背包是最最基础的,其他背包也是在01背包的基础上稍作变化。 13 | 14 | 所以我才花费这么大精力去讲解01背包。 15 | 16 | 关于其他几种常用的背包,大家看这张图就了然于胸了: 17 | 18 | ![416.分割等和子集1](https://img-blog.csdnimg.cn/20210117171307407.png) 19 | 20 | 本文用动规五部曲详细讲解了01背包的二维dp数组的实现方法,大家其实可以发现最简单的是推导公式了,推导公式估计看一遍就记下来了,但难就难在确定初始化和遍历顺序上。 21 | 22 | 1. 确定dp数组以及下标的含义 23 | 24 | dp[i][j] 表示从下标为[0-i]的物品里任意取,放进容量为j的背包,价值总和最大是多少。 25 | 26 | 2. 确定递推公式 27 | 28 | dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]); 29 | 30 | 3. dp数组如何初始化 31 | 32 | ```CPP 33 | // 初始化 dp 34 | vector> dp(weight.size() + 1, vector(bagWeight + 1, 0)); 35 | for (int j = bagWeight; j >= weight[0]; j--) { 36 | dp[0][j] = dp[0][j - weight[0]] + value[0]; 37 | } 38 | ``` 39 | 40 | 4. 确定遍历顺序 41 | 42 | **01背包二维dp数组在遍历顺序上,外层遍历物品 ,内层遍历背包容量 和 外层遍历背包容量 ,内层遍历物品 都是可以的!** 43 | 44 | 但是先遍历物品更好理解。代码如下: 45 | 46 | ```CPP 47 | // weight数组的大小 就是物品个数 48 | for(int i = 1; i < weight.size(); i++) { // 遍历物品 49 | for(int j = 0; j <= bagWeight; j++) { // 遍历背包容量 50 | if (j < weight[i]) dp[i][j] = dp[i - 1][j]; // 这个是为了展现dp数组里元素的变化 51 | else dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]); 52 | 53 | } 54 | } 55 | ``` 56 | 57 | 5. 举例推导dp数组 58 | 59 | 背包最大重量为4。 60 | 61 | 物品为: 62 | 63 | | | 重量 | 价值 | 64 | | --- | --- | --- | 65 | | 物品0 | 1 | 15 | 66 | | 物品1 | 3 | 20 | 67 | | 物品2 | 4 | 30 | 68 | 69 | 来看一下对应的dp数组的数值,如图: 70 | 71 | ![动态规划-背包问题4](https://img-blog.csdnimg.cn/20210118163425129.jpg) 72 | 73 | 最终结果就是dp[2][4]。 74 | 75 | 76 | ## 周二 77 | 78 | [动态规划:关于01背包问题,你该了解这些!(滚动数组)](https://programmercarl.com/背包理论基础01背包-2.html)中把01背包的一维dp数组(滚动数组)实现详细讲解了一遍。 79 | 80 | 分析一下和二维dp数组有什么区别,在初始化和遍历顺序上又有什么差异? 81 | 82 | 最后总结了一道朴实无华的背包面试题。 83 | 84 | 要求候选人先实现一个纯二维的01背包,如果写出来了,然后再问为什么两个for循环的嵌套顺序这么写?反过来写行不行?再讲一讲初始化的逻辑。 85 | 86 | 然后要求实现一个一维数组的01背包,最后再问,一维数组的01背包,两个for循环的顺序反过来写行不行?为什么? 87 | 88 | 这几个问题就可以考察出候选人的算法功底了。 89 | 90 | 01背包一维数组分析如下: 91 | 92 | 1. 确定dp数组的定义 93 | 94 | 在一维dp数组中,dp[j]表示:容量为j的背包,所背的物品价值可以最大为dp[j]。 95 | 96 | 2. 一维dp数组的递推公式 97 | 98 | ``` 99 | dp[j] = max(dp[j], dp[j - weight[i]] + value[i]); 100 | ``` 101 | 102 | 3. 一维dp数组如何初始化 103 | 104 | 如果物品价值都是大于0的,所以dp数组初始化的时候,都初始为0就可以了。 105 | 106 | 4. 一维dp数组遍历顺序 107 | 108 | 代码如下: 109 | 110 | ```CPP 111 | for(int i = 0; i < weight.size(); i++) { // 遍历物品 112 | for(int j = bagWeight; j >= weight[i]; j--) { // 遍历背包容量 113 | dp[j] = max(dp[j], dp[j - weight[i]] + value[i]); 114 | 115 | } 116 | } 117 | ``` 118 | 119 | 5. 举例推导dp数组 120 | 121 | 一维dp,分别用物品0,物品1,物品2 来遍历背包,最终得到结果如下: 122 | 123 | ![动态规划-背包问题9](https://img-blog.csdnimg.cn/20210110103614769.png) 124 | 125 | 126 | ## 周三 127 | 128 | [动态规划:416. 分割等和子集](https://programmercarl.com/0416.分割等和子集.html)中我们开始用01背包来解决问题。 129 | 130 | 只有确定了如下四点,才能把01背包问题套到本题上来。 131 | 132 | * 背包的体积为sum / 2 133 | * 背包要放入的商品(集合里的元素)重量为 元素的数值,价值也为元素的数值 134 | * 背包如何正好装满,说明找到了总和为 sum / 2 的子集。 135 | * 背包中每一个元素是不可重复放入。 136 | 137 | 接下来就是一个完整的01背包问题,大家应该可以轻松做出了。 138 | 139 | ## 周四 140 | 141 | [动态规划:1049. 最后一块石头的重量 II](https://programmercarl.com/1049.最后一块石头的重量II.html)这道题目其实和[动态规划:416. 分割等和子集](https://programmercarl.com/0416.分割等和子集.html)是非常像的。 142 | 143 | 本题其实就是尽量让石头分成重量相同的两堆,相撞之后剩下的石头最小,这样就化解成01背包问题了。 144 | 145 | [动态规划:416. 分割等和子集](https://programmercarl.com/0416.分割等和子集.html)相当于是求背包是否正好装满,而本题是求背包最多能装多少。 146 | 147 | 这两道题目是对dp[target]的处理方式不同。这也考验的对dp[i]定义的理解。 148 | 149 | 150 | ## 总结 151 | 152 | 总体来说,本周信息量还是比较大的,特别对于对动态规划还不够了解的同学。 153 | 154 | 但如果坚持下来把,我在文章中列出的每一个问题,都仔细思考,消化为自己的知识,那么进步一定是飞速的。 155 | 156 | 有的同学可能看了看背包递推公式,上来就能撸它几道题目,然后背包问题就这么过去了,其实这样是很不牢固的。 157 | 158 | 就像是我们讲解01背包的时候,花了那么大力气才把每一个细节都讲清楚,这里其实是基础,后面的背包问题怎么变,基础比较牢固自然会有自己的一套思考过程。 159 | 160 | 161 |
162 | -------------------------------------------------------------------------------- /problems/0657.机器人能否返回原点.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 |

参与本项目,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!

6 | 7 | 8 | # 657. 机器人能否返回原点 9 | 10 | [力扣题目链接](https://leetcode-cn.com/problems/robot-return-to-origin/) 11 | 12 | 在二维平面上,有一个机器人从原点 (0, 0) 开始。给出它的移动顺序,判断这个机器人在完成移动后是否在 (0, 0) 处结束。 13 | 14 | 移动顺序由字符串表示。字符 move[i] 表示其第 i 次移动。机器人的有效动作有 R(右),L(左),U(上)和 D(下)。如果机器人在完成所有动作后返回原点,则返回 true。否则,返回 false。 15 | 16 | 注意:机器人“面朝”的方向无关紧要。 “R” 将始终使机器人向右移动一次,“L” 将始终向左移动等。此外,假设每次移动机器人的移动幅度相同。 17 | 18 |   19 | 20 | 示例 1: 21 | * 输入: "UD" 22 | * 输出: true 23 | * 解释:机器人向上移动一次,然后向下移动一次。所有动作都具有相同的幅度,因此它最终回到它开始的原点。因此,我们返回 true。 24 | 25 | 示例 2: 26 | * 输入: "LL" 27 | * 输出: false 28 | * 解释:机器人向左移动两次。它最终位于原点的左侧,距原点有两次 “移动” 的距离。我们返回 false,因为它在移动结束时没有返回原点。 29 | 30 | 31 | 32 | # 思路 33 | 34 | 这道题目还是挺简单的,大家不要想复杂了,一波哈希法又一波图论算法啥的,哈哈。 35 | 36 | 其实就是,x,y坐标,初始为0,然后: 37 | * if (moves[i] == 'U') y++; 38 | * if (moves[i] == 'D') y--; 39 | * if (moves[i] == 'L') x--; 40 | * if (moves[i] == 'R') x++; 41 | 42 | 最后判断一下x,y是否回到了(0, 0)位置就可以了。 43 | 44 | 如图所示: 45 | 46 | 47 | C++代码如下: 48 | 49 | ```CPP 50 | class Solution { 51 | public: 52 | bool judgeCircle(string moves) { 53 | int x = 0, y = 0; 54 | for (int i = 0; i < moves.size(); i++) { 55 | if (moves[i] == 'U') y++; 56 | if (moves[i] == 'D') y--; 57 | if (moves[i] == 'L') x--; 58 | if (moves[i] == 'R') x++; 59 | } 60 | if (x == 0 && y == 0) return true; 61 | return false; 62 | } 63 | }; 64 | ``` 65 | 66 | 67 | # 其他语言版本 68 | 69 | ## Java 70 | 71 | ```java 72 | // 时间复杂度:O(n) 73 | // 空间复杂度:如果采用 toCharArray,则是 O(n);如果使用 charAt,则是 O(1) 74 | class Solution { 75 | public boolean judgeCircle(String moves) { 76 | int x = 0; 77 | int y = 0; 78 | for (char c : moves.toCharArray()) { 79 | if (c == 'U') y++; 80 | if (c == 'D') y--; 81 | if (c == 'L') x++; 82 | if (c == 'R') x--; 83 | } 84 | return x == 0 && y == 0; 85 | } 86 | } 87 | ``` 88 | 89 | ## Python 90 | 91 | ```python 92 | # 时间复杂度:O(n) 93 | # 空间复杂度:O(1) 94 | class Solution: 95 | def judgeCircle(self, moves: str) -> bool: 96 | x = 0 # 记录当前位置 97 | y = 0 98 | for i in range(len(moves)): 99 | if (moves[i] == 'U'): 100 | y += 1 101 | if (moves[i] == 'D'): 102 | y -= 1 103 | if (moves[i] == 'L'): 104 | x += 1 105 | if (moves[i] == 'R'): 106 | x -= 1 107 | return x == 0 and y == 0 108 | ``` 109 | 110 | ## Go 111 | 112 | ```go 113 | func judgeCircle(moves string) bool { 114 | x := 0 115 | y := 0 116 | for i := 0; i < len(moves); i++ { 117 | if moves[i] == 'U' { 118 | y++ 119 | } 120 | if moves[i] == 'D' { 121 | y-- 122 | } 123 | if moves[i] == 'L' { 124 | x++ 125 | } 126 | if moves[i] == 'R' { 127 | x-- 128 | } 129 | } 130 | return x == 0 && y == 0; 131 | } 132 | ``` 133 | 134 | ## JavaScript 135 | 136 | ```js 137 | // 时间复杂度:O(n) 138 | // 空间复杂度:O(1) 139 | var judgeCircle = function(moves) { 140 | var x = 0; // 记录当前位置 141 | var y = 0; 142 | for (var i = 0; i < moves.length; i++) { 143 | if (moves[i] == 'U') y++; 144 | if (moves[i] == 'D') y--; 145 | if (moves[i] == 'L') x++; 146 | if (moves[i] == 'R') x--; 147 | } 148 | return x == 0 && y == 0; 149 | }; 150 | ``` 151 | 152 | 153 | ----------------------- 154 |
155 | -------------------------------------------------------------------------------- /problems/0055.跳跃游戏.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 |

参与本项目,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!

6 | 7 | 8 | # 55. 跳跃游戏 9 | 10 | [力扣题目链接](https://leetcode-cn.com/problems/jump-game/) 11 | 12 | 给定一个非负整数数组,你最初位于数组的第一个位置。 13 | 14 | 数组中的每个元素代表你在该位置可以跳跃的最大长度。 15 | 16 | 判断你是否能够到达最后一个位置。 17 | 18 | 示例 1: 19 | * 输入: [2,3,1,1,4] 20 | * 输出: true 21 | * 解释: 我们可以先跳 1 步,从位置 0 到达 位置 1, 然后再从位置 1 跳 3 步到达最后一个位置。 22 | 23 | 示例 2: 24 | * 输入: [3,2,1,0,4] 25 | * 输出: false 26 | * 解释: 无论怎样,你总会到达索引为 3 的位置。但该位置的最大跳跃长度是 0 , 所以你永远不可能到达最后一个位置。 27 | 28 | 29 | ## 思路 30 | 31 | 刚看到本题一开始可能想:当前位置元素如果是3,我究竟是跳一步呢,还是两步呢,还是三步呢,究竟跳几步才是最优呢? 32 | 33 | 其实跳几步无所谓,关键在于可跳的覆盖范围! 34 | 35 | 不一定非要明确一次究竟跳几步,每次取最大的跳跃步数,这个就是可以跳跃的覆盖范围。 36 | 37 | 这个范围内,别管是怎么跳的,反正一定可以跳过来。 38 | 39 | **那么这个问题就转化为跳跃覆盖范围究竟可不可以覆盖到终点!** 40 | 41 | 每次移动取最大跳跃步数(得到最大的覆盖范围),每移动一个单位,就更新最大覆盖范围。 42 | 43 | **贪心算法局部最优解:每次取最大跳跃步数(取最大覆盖范围),整体最优解:最后得到整体最大覆盖范围,看是否能到终点**。 44 | 45 | 局部最优推出全局最优,找不出反例,试试贪心! 46 | 47 | 如图: 48 | 49 | ![55.跳跃游戏](https://img-blog.csdnimg.cn/20201124154758229.png) 50 | 51 | i每次移动只能在cover的范围内移动,每移动一个元素,cover得到该元素数值(新的覆盖范围)的补充,让i继续移动下去。 52 | 53 | 而cover每次只取 max(该元素数值补充后的范围, cover本身范围)。 54 | 55 | 如果cover大于等于了终点下标,直接return true就可以了。 56 | 57 | C++代码如下: 58 | 59 | ```CPP 60 | class Solution { 61 | public: 62 | bool canJump(vector& nums) { 63 | int cover = 0; 64 | if (nums.size() == 1) return true; // 只有一个元素,就是能达到 65 | for (int i = 0; i <= cover; i++) { // 注意这里是小于等于cover 66 | cover = max(i + nums[i], cover); 67 | if (cover >= nums.size() - 1) return true; // 说明可以覆盖到终点了 68 | } 69 | return false; 70 | } 71 | }; 72 | ``` 73 | ## 总结 74 | 75 | 这道题目关键点在于:不用拘泥于每次究竟跳跳几步,而是看覆盖范围,覆盖范围内一定是可以跳过来的,不用管是怎么跳的。 76 | 77 | 大家可以看出思路想出来了,代码还是非常简单的。 78 | 79 | 一些同学可能感觉,我在讲贪心系列的时候,题目和题目之间貌似没有什么联系? 80 | 81 | **是真的就是没什么联系,因为贪心无套路!**没有个整体的贪心框架解决一些列问题,只能是接触各种类型的题目锻炼自己的贪心思维! 82 | 83 | ## 其他语言版本 84 | 85 | 86 | ### Java 87 | ```Java 88 | class Solution { 89 | public boolean canJump(int[] nums) { 90 | if (nums.length == 1) { 91 | return true; 92 | } 93 | //覆盖范围, 初始覆盖范围应该是0,因为下面的迭代是从下标0开始的 94 | int coverRange = 0; 95 | //在覆盖范围内更新最大的覆盖范围 96 | for (int i = 0; i <= coverRange; i++) { 97 | coverRange = Math.max(coverRange, i + nums[i]); 98 | if (coverRange >= nums.length - 1) { 99 | return true; 100 | } 101 | } 102 | return false; 103 | } 104 | } 105 | ``` 106 | 107 | ### Python 108 | ```python 109 | class Solution: 110 | def canJump(self, nums: List[int]) -> bool: 111 | cover = 0 112 | if len(nums) == 1: return True 113 | i = 0 114 | # python不支持动态修改for循环中变量,使用while循环代替 115 | while i <= cover: 116 | cover = max(i + nums[i], cover) 117 | if cover >= len(nums) - 1: return True 118 | i += 1 119 | return False 120 | ``` 121 | 122 | ### Go 123 | ```Go 124 | func canJUmp(nums []int) bool { 125 | if len(nums)<=1{ 126 | return true 127 | } 128 | dp:=make([]bool,len(nums)) 129 | dp[0]=true 130 | for i:=1;i=0;j--{ 132 | if dp[j]&&nums[j]+j>=i{ 133 | dp[i]=true 134 | break 135 | } 136 | } 137 | } 138 | return dp[len(nums)-1] 139 | } 140 | ``` 141 | 142 | ### Javascript 143 | ```Javascript 144 | var canJump = function(nums) { 145 | if(nums.length === 1) return true 146 | let cover = 0 147 | for(let i = 0; i <= cover; i++) { 148 | cover = Math.max(cover, i + nums[i]) 149 | if(cover >= nums.length - 1) { 150 | return true 151 | } 152 | } 153 | return false 154 | }; 155 | ``` 156 | 157 | 158 | ----------------------- 159 |
160 | -------------------------------------------------------------------------------- /problems/回溯算法理论基础.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 |

参与本项目,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!

6 | 7 | # 回溯算法理论基础 8 | 9 | ## 题目分类大纲如下: 10 | 11 | 回溯算法大纲 12 | 13 | 可以配合我的B站视频:[带你学透回溯算法(理论篇)](https://www.bilibili.com/video/BV1cy4y167mM/) 一起学习! 14 | 15 | ## 什么是回溯法 16 | 17 | 回溯法也可以叫做回溯搜索法,它是一种搜索的方式。 18 | 19 | 在二叉树系列中,我们已经不止一次,提到了回溯,例如[二叉树:以为使用了递归,其实还隐藏着回溯](https://programmercarl.com/二叉树中递归带着回溯.html)。 20 | 21 | 回溯是递归的副产品,只要有递归就会有回溯。 22 | 23 | **所以以下讲解中,回溯函数也就是递归函数,指的都是一个函数**。 24 | 25 | ## 回溯法的效率 26 | 27 | 回溯法的性能如何呢,这里要和大家说清楚了,**虽然回溯法很难,很不好理解,但是回溯法并不是什么高效的算法**。 28 | 29 | **因为回溯的本质是穷举,穷举所有可能,然后选出我们想要的答案**,如果想让回溯法高效一些,可以加一些剪枝的操作,但也改不了回溯法就是穷举的本质。 30 | 31 | 那么既然回溯法并不高效为什么还要用它呢? 32 | 33 | 因为没得选,一些问题能暴力搜出来就不错了,撑死了再剪枝一下,还没有更高效的解法。 34 | 35 | 此时大家应该好奇了,都什么问题,这么牛逼,只能暴力搜索。 36 | 37 | ## 回溯法解决的问题 38 | 39 | 回溯法,一般可以解决如下几种问题: 40 | 41 | * 组合问题:N个数里面按一定规则找出k个数的集合 42 | * 切割问题:一个字符串按一定规则有几种切割方式 43 | * 子集问题:一个N个数的集合里有多少符合条件的子集 44 | * 排列问题:N个数按一定规则全排列,有几种排列方式 45 | * 棋盘问题:N皇后,解数独等等 46 | 47 | **相信大家看着这些之后会发现,每个问题,都不简单!** 48 | 49 | 50 | 另外,会有一些同学可能分不清什么是组合,什么是排列? 51 | 52 | **组合是不强调元素顺序的,排列是强调元素顺序**。 53 | 54 | 例如:{1, 2} 和 {2, 1} 在组合上,就是一个集合,因为不强调顺序,而要是排列的话,{1, 2} 和 {2, 1} 就是两个集合了。 55 | 56 | 记住组合无序,排列有序,就可以了。 57 | 58 | ## 如何理解回溯法 59 | 60 | **回溯法解决的问题都可以抽象为树形结构**,是的,我指的是所有回溯法的问题都可以抽象为树形结构! 61 | 62 | 因为回溯法解决的都是在集合中递归查找子集,**集合的大小就构成了树的宽度,递归的深度,都构成的树的深度**。 63 | 64 | 递归就要有终止条件,所以必然是一棵高度有限的树(N叉树)。 65 | 66 | 这块可能初学者还不太理解,后面的回溯算法解决的所有题目中,我都会强调这一点并画图举相应的例子,现在有一个印象就行。 67 | 68 | 69 | ## 回溯法模板 70 | 71 | 这里给出Carl总结的回溯算法模板。 72 | 73 | 在讲[二叉树的递归](https://programmercarl.com/二叉树的递归遍历.html)中我们说了递归三部曲,这里我再给大家列出回溯三部曲。 74 | 75 | * 回溯函数模板返回值以及参数 76 | 77 | 在回溯算法中,我的习惯是函数起名字为backtracking,这个起名大家随意。 78 | 79 | 回溯算法中函数返回值一般为void。 80 | 81 | 再来看一下参数,因为回溯算法需要的参数可不像二叉树递归的时候那么容易一次性确定下来,所以一般是先写逻辑,然后需要什么参数,就填什么参数。 82 | 83 | 但后面的回溯题目的讲解中,为了方便大家理解,我在一开始就帮大家把参数确定下来。 84 | 85 | 回溯函数伪代码如下: 86 | 87 | ``` 88 | void backtracking(参数) 89 | ``` 90 | 91 | * 回溯函数终止条件 92 | 93 | 既然是树形结构,那么我们在讲解[二叉树的递归](https://programmercarl.com/二叉树的递归遍历.html)的时候,就知道遍历树形结构一定要有终止条件。 94 | 95 | 所以回溯也有要终止条件。 96 | 97 | 什么时候达到了终止条件,树中就可以看出,一般来说搜到叶子节点了,也就找到了满足条件的一条答案,把这个答案存放起来,并结束本层递归。 98 | 99 | 所以回溯函数终止条件伪代码如下: 100 | ``` 101 | if (终止条件) { 102 | 存放结果; 103 | return; 104 | } 105 | ``` 106 | 107 | * 回溯搜索的遍历过程 108 | 109 | 在上面我们提到了,回溯法一般是在集合中递归搜索,集合的大小构成了树的宽度,递归的深度构成的树的深度。 110 | 111 | 如图: 112 | 113 | ![回溯算法理论基础](https://img-blog.csdnimg.cn/20210130173631174.png) 114 | 115 | 注意图中,我特意举例集合大小和孩子的数量是相等的! 116 | 117 | 回溯函数遍历过程伪代码如下: 118 | ``` 119 | for (选择:本层集合中元素(树中节点孩子的数量就是集合的大小)) { 120 | 处理节点; 121 | backtracking(路径,选择列表); // 递归 122 | 回溯,撤销处理结果 123 | } 124 | ``` 125 | 126 | 127 | for循环就是遍历集合区间,可以理解一个节点有多少个孩子,这个for循环就执行多少次。 128 | 129 | backtracking这里自己调用自己,实现递归。 130 | 131 | 大家可以从图中看出**for循环可以理解是横向遍历,backtracking(递归)就是纵向遍历**,这样就把这棵树全遍历完了,一般来说,搜索叶子节点就是找的其中一个结果了。 132 | 133 | 分析完过程,回溯算法模板框架如下: 134 | 135 | ``` 136 | void backtracking(参数) { 137 | if (终止条件) { 138 | 存放结果; 139 | return; 140 | } 141 | 142 | for (选择:本层集合中元素(树中节点孩子的数量就是集合的大小)) { 143 | 处理节点; 144 | backtracking(路径,选择列表); // 递归 145 | 回溯,撤销处理结果 146 | } 147 | } 148 | 149 | ``` 150 | 151 | **这份模板很重要,后面做回溯法的题目都靠它了!** 152 | 153 | 如果从来没有学过回溯算法的录友们,看到这里会有点懵,后面开始讲解具体题目的时候就会好一些了,已经做过回溯法题目的录友,看到这里应该会感同身受了。 154 | 155 | ## 总结 156 | 157 | 本篇我们讲解了,什么是回溯算法,知道了回溯和递归是相辅相成的。 158 | 159 | 接着提到了回溯法的效率,回溯法其实就是暴力查找,并不是什么高效的算法。 160 | 161 | 然后列出了回溯法可以解决几类问题,可以看出每一类问题都不简单。 162 | 163 | 最后我们讲到回溯法解决的问题都可以抽象为树形结构(N叉树),并给出了回溯法的模板。 164 | 165 | 今天是回溯算法的第一天,按照惯例Carl都是先概述一波,然后在开始讲解具体题目,没有接触过回溯法的同学刚学起来有点看不懂很正常,后面和具体题目结合起来会好一些。 166 | 167 | 168 | 169 | 170 | 171 | 172 | ----------------------- 173 |
174 | -------------------------------------------------------------------------------- /problems/周总结/20210114动规周末总结.md: -------------------------------------------------------------------------------- 1 | 2 | ## 周一 3 | 4 | [动态规划:不同路径](https://programmercarl.com/0062.不同路径.html)中求从出发点到终点有几种路径,只能向下或者向右移动一步。 5 | 6 | 我们提供了三种方法,但重点讲解的还是动规,也是需要重点掌握的。 7 | 8 | **dp[i][j]定义 :表示从(0 ,0)出发,到(i, j) 有dp[i][j]条不同的路径**。 9 | 10 | 本题在初始化的时候需要点思考了,即: 11 | 12 | dp[i][0]一定都是1,因为从(0, 0)的位置到(i, 0)的路径只有一条,那么dp[0][j]也同理。 13 | 14 | 所以初始化为: 15 | 16 | ``` 17 | for (int i = 0; i < m; i++) dp[i][0] = 1; 18 | for (int j = 0; j < n; j++) dp[0][j] = 1; 19 | ``` 20 | 21 | 这里已经不像之前做过的题目,随便赋个0就行的。 22 | 23 | 遍历顺序以及递推公式: 24 | 25 | ``` 26 | for (int i = 1; i < m; i++) { 27 | for (int j = 1; j < n; j++) { 28 | dp[i][j] = dp[i - 1][j] + dp[i][j - 1]; 29 | } 30 | } 31 | ``` 32 | 33 | ![62.不同路径1](https://img-blog.csdnimg.cn/20201209113631392.png) 34 | 35 | 36 | ## 周二 37 | 38 | [动态规划:不同路径还不够,要有障碍!](https://programmercarl.com/0063.不同路径II.html)相对于[动态规划:不同路径](https://programmercarl.com/0062.不同路径.html)添加了障碍。 39 | 40 | dp[i][j]定义依然是:表示从(0 ,0)出发,到(i, j) 有dp[i][j]条不同的路径。 41 | 42 | 43 | 本题难点在于初始化,如果(i, 0) 这条边有了障碍之后,障碍之后(包括障碍)都是走不到的位置了,所以障碍之后的dp[i][0]应该还是初始值0。 44 | 45 | 如图: 46 | 47 | ![63.不同路径II](https://img-blog.csdnimg.cn/20210104114513928.png) 48 | 49 | 50 | 这里难住了不少同学,代码如下: 51 | 52 | ``` 53 | vector> dp(m, vector(n, 0)); 54 | for (int i = 0; i < m && obstacleGrid[i][0] == 0; i++) dp[i][0] = 1; 55 | for (int j = 0; j < n && obstacleGrid[0][j] == 0; j++) dp[0][j] = 1; 56 | ``` 57 | 58 | 59 | 递推公式只要考虑一下障碍,就不赋值了就可以了,如下: 60 | 61 | ``` 62 | for (int i = 1; i < m; i++) { 63 | for (int j = 1; j < n; j++) { 64 | if (obstacleGrid[i][j] == 1) continue; 65 | dp[i][j] = dp[i - 1][j] + dp[i][j - 1]; 66 | } 67 | } 68 | ``` 69 | 70 | 拿示例1来举例如题: 71 | 72 | ![63.不同路径II1](https://img-blog.csdnimg.cn/20210104114548983.png) 73 | 74 | 对应的dp table 如图: 75 | 76 | ![63.不同路径II2](https://img-blog.csdnimg.cn/20210104114610256.png) 77 | 78 | 79 | ## 周三 80 | 81 | [动态规划:整数拆分,你要怎么拆?](https://programmercarl.com/0343.整数拆分.html)给出一个整数,问有多少种拆分的方法。 82 | 83 | 这道题目就有点难度了,题目中dp我也给出了两种方法,但通过两种方法的比较可以看出,对dp数组定义的理解,以及dp数组初始化的重要性。 84 | 85 | 86 | **dp[i]定义:分拆数字i,可以得到的最大乘积为dp[i]**。 87 | 88 | 本题中dp[i]的初始化其实也很有考究,严格从dp[i]的定义来说,dp[0] dp[1] 就不应该初始化,也就是没有意义的数值。 89 | 90 | 拆分0和拆分1的最大乘积是多少? 91 | 92 | 这是无解的。 93 | 94 | 所以题解里我只初始化dp[2] = 1,从dp[i]的定义来说,拆分数字2,得到的最大乘积是1,这个没有任何异议! 95 | 96 | ``` 97 | vector dp(n + 1); 98 | dp[2] = 1; 99 | ``` 100 | 101 | 遍历顺序以及递推公式: 102 | 103 | ``` 104 | for (int i = 3; i <= n ; i++) { 105 | for (int j = 1; j < i - 1; j++) { 106 | dp[i] = max(dp[i], max((i - j) * j, dp[i - j] * j)); 107 | } 108 | } 109 | ``` 110 | 举例当n为10 的时候,dp数组里的数值,如下: 111 | 112 | ![343.整数拆分](https://img-blog.csdnimg.cn/20210104173021581.png) 113 | 114 | 115 | 116 | 一些录友可能对为什么没有拆分j没有想清楚。 117 | 118 | 其实可以模拟一下哈,拆分j的情况,在遍历j的过程中dp[i - j]其实都计算过了。 119 | 120 | 例如 i= 10,j = 5,i-j = 5,如果把j查分为 2 和 3,其实在j = 2 的时候,i-j= 8 ,拆分i-j的时候就可以拆出来一个3了。 121 | 122 | **或者也可以理解j是拆分i的第一个整数**。 123 | 124 | [动态规划:整数拆分,你要怎么拆?](https://programmercarl.com/0343.整数拆分.html)总结里,我也给出了递推公式dp[i] = max(dp[i], dp[i - j] * dp[j])这种写法。 125 | 126 | 对于这种写法,一位录友总结的很好,意思就是:如果递推公式是dp[i-j] * dp[j],这样就相当于强制把一个数至少拆分成四份。 127 | 128 | dp[i-j]至少是两个数的乘积,dp[j]又至少是两个数的乘积,但其实3以下的数,数的本身比任何它的拆分乘积都要大了,所以文章中初始化的时候才要特殊处理。 129 | 130 | ## 周四 131 | 132 | [动态规划:不同的二叉搜索树](https://programmercarl.com/0096.不同的二叉搜索树.html)给出n个不同的节点求能组成多少个不同二叉搜索树。 133 | 134 | 这道题目还是比较难的,想到用动态规划的方法就很不容易了! 135 | 136 | **dp[i]定义 :1到i为节点组成的二叉搜索树的个数为dp[i]**。 137 | 138 | 递推公式:dp[i] += dp[j - 1] * dp[i - j]; ,j-1 为j为头结点左子树节点数量,i-j 为以j为头结点右子树节点数量 139 | 140 | dp数组如何初始化:只需要初始化dp[0]就可以了,推导的基础,都是dp[0]。 141 | 142 | n为5时候的dp数组状态如图: 143 | 144 | ![96.不同的二叉搜索树3](https://img-blog.csdnimg.cn/20210107093253987.png) 145 | 146 | ## 总结 147 | 148 | 本周题目已经开始点难度了,特别是[动态规划:不同的二叉搜索树](https://programmercarl.com/0096.不同的二叉搜索树.html)这道题目,明显感觉阅读量很低,可能是因为确实有点难吧。 149 | 150 | 我现在也陷入了纠结,题目一简单,就会有录友和我反馈说题目太简单了,题目一难,阅读量就特别低。 151 | 152 | 我也好难那,哈哈哈。 153 | 154 | **但我还会坚持规划好的路线,难度循序渐进,并以面试经典题目为准,该简单的时候就是简单,同时也不会因为阅读量低就放弃有难度的题目!**。 155 | 156 | 录友们看到这是不是得给个Carl点个赞啊[让我看看]。 157 | 158 | 预告,我们下周正式开始讲解背包问题,经典的不能再经典,也是比较难的一类动态规划的题目了,录友们上车抓稳咯。 159 | 160 |
161 | -------------------------------------------------------------------------------- /problems/哈希表总结.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 |

参与本项目,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!

6 | 7 | 8 | > 哈希表总结篇如约而至 9 | 10 | 11 | # 哈希表理论基础 12 | 13 | 在[关于哈希表,你该了解这些!](https://programmercarl.com/哈希表理论基础.html)中,我们介绍了哈希表的基础理论知识,不同于枯燥的讲解,这里介绍了都是对刷题有帮助的理论知识点。 14 | 15 | **一般来说哈希表都是用来快速判断一个元素是否出现集合里**。 16 | 17 | 对于哈希表,要知道**哈希函数**和**哈希碰撞**在哈希表中的作用. 18 | 19 | 哈希函数是把传入的key映射到符号表的索引上。 20 | 21 | 哈希碰撞处理有多个key映射到相同索引上时的情景,处理碰撞的普遍方式是拉链法和线性探测法。 22 | 23 | 接下来是常见的三种哈希结构: 24 | 25 | * 数组 26 | * set(集合) 27 | * map(映射) 28 | 29 | 在C++语言中,set 和 map 都分别提供了三种数据结构,每种数据结构的底层实现和用途都有所不同,在[关于哈希表,你该了解这些!](https://programmercarl.com/哈希表理论基础.html)中我给出了详细分析,这一知识点很重要! 30 | 31 | 例如什么时候用std::set,什么时候用std::multiset,什么时候用std::unordered_set,都是很有考究的。 32 | 33 | **只有对这些数据结构的底层实现很熟悉,才能灵活使用,否则很容易写出效率低下的程序**。 34 | 35 | # 哈希表经典题目 36 | 37 | ## 数组作为哈希表 38 | 39 | 一些应用场景就是为数组量身定做的。 40 | 41 | 在[242.有效的字母异位词](https://programmercarl.com/0242.有效的字母异位词.html)中,我们提到了数组就是简单的哈希表,但是数组的大小是受限的! 42 | 43 | 这道题目包含小写字母,那么使用数组来做哈希最合适不过。 44 | 45 | 在[383.赎金信](https://programmercarl.com/0383.赎金信.html)中同样要求只有小写字母,那么就给我们浓浓的暗示,用数组! 46 | 47 | 本题和[242.有效的字母异位词](https://programmercarl.com/0242.有效的字母异位词.html)很像,[242.有效的字母异位词](https://programmercarl.com/0242.有效的字母异位词.html)是求 字符串a 和 字符串b 是否可以相互组成,在[383.赎金信](https://programmercarl.com/0383.赎金信.html)中是求字符串a能否组成字符串b,而不用管字符串b 能不能组成字符串a。 48 | 49 | 一些同学可能想,用数组干啥,都用map不就完事了。 50 | 51 | **上面两道题目用map确实可以,但使用map的空间消耗要比数组大一些,因为map要维护红黑树或者符号表,而且还要做哈希函数的运算。所以数组更加简单直接有效!** 52 | 53 | 54 | ## set作为哈希表 55 | 56 | 在[349. 两个数组的交集](https://programmercarl.com/0349.两个数组的交集.html)中我们给出了什么时候用数组就不行了,需要用set。 57 | 58 | 这道题目没有限制数值的大小,就无法使用数组来做哈希表了。 59 | 60 | **主要因为如下两点:** 61 | 62 | * 数组的大小是有限的,受到系统栈空间(不是数据结构的栈)的限制。 63 | * 如果数组空间够大,但哈希值比较少、特别分散、跨度非常大,使用数组就造成空间的极大浪费。 64 | 65 | 所以此时一样的做映射的话,就可以使用set了。 66 | 67 | 关于set,C++ 给提供了如下三种可用的数据结构:(详情请看[关于哈希表,你该了解这些!](https://programmercarl.com/哈希表理论基础.html)) 68 | 69 | * std::set 70 | * std::multiset 71 | * std::unordered_set 72 | 73 | std::set和std::multiset底层实现都是红黑树,std::unordered_set的底层实现是哈希, 使用unordered_set 读写效率是最高的,本题并不需要对数据进行排序,而且还不要让数据重复,所以选择unordered_set。 74 | 75 | 在[202.快乐数](https://programmercarl.com/0202.快乐数.html)中,我们再次使用了unordered_set来判断一个数是否重复出现过。 76 | 77 | 78 | ## map作为哈希表 79 | 80 | 在[1.两数之和](https://programmercarl.com/0001.两数之和.html)中map正式登场。 81 | 82 | 来说一说:使用数组和set来做哈希法的局限。 83 | 84 | * 数组的大小是受限制的,而且如果元素很少,而哈希值太大会造成内存空间的浪费。 85 | * set是一个集合,里面放的元素只能是一个key,而两数之和这道题目,不仅要判断y是否存在而且还要记录y的下标位置,因为要返回x 和 y的下标。所以set 也不能用。 86 | 87 | map是一种``的结构,本题可以用key保存数值,用value在保存数值所在的下标。所以使用map最为合适。 88 | 89 | C++提供如下三种map::(详情请看[关于哈希表,你该了解这些!](https://programmercarl.com/哈希表理论基础.html)) 90 | 91 | * std::map 92 | * std::multimap 93 | * std::unordered_map 94 | 95 | std::unordered_map 底层实现为哈希,std::map 和std::multimap 的底层实现是红黑树。 96 | 97 | 同理,std::map 和std::multimap 的key也是有序的(这个问题也经常作为面试题,考察对语言容器底层的理解),[1.两数之和](https://programmercarl.com/0001.两数之和.html)中并不需要key有序,选择std::unordered_map 效率更高! 98 | 99 | 在[454.四数相加](https://programmercarl.com/0454.四数相加II.html)中我们提到了其实需要哈希的地方都能找到map的身影。 100 | 101 | 本题咋眼一看好像和[18. 四数之和](https://programmercarl.com/0018.四数之和.html),[15.三数之和](https://programmercarl.com/0015.三数之和.html)差不多,其实差很多! 102 | 103 | **关键差别是本题为四个独立的数组,只要找到A[i] + B[j] + C[k] + D[l] = 0就可以,不用考虑重复问题,而[18. 四数之和](https://programmercarl.com/0018.四数之和.html),[15.三数之和](https://programmercarl.com/0015.三数之和.html)是一个数组(集合)里找到和为0的组合,可就难很多了!** 104 | 105 | 用哈希法解决了两数之和,很多同学会感觉用哈希法也可以解决三数之和,四数之和。 106 | 107 | 其实是可以解决,但是非常麻烦,需要去重导致代码效率很低。 108 | 109 | 在[15.三数之和](https://programmercarl.com/0015.三数之和.html)中我给出了哈希法和双指针两个解法,大家就可以体会到,使用哈希法还是比较麻烦的。 110 | 111 | 所以18. 四数之和,15.三数之和都推荐使用双指针法! 112 | 113 | # 总结 114 | 115 | 对于哈希表的知识相信很多同学都知道,但是没有成体系。 116 | 117 | 本篇我们从哈希表的理论基础到数组、set和map的经典应用,把哈希表的整个全貌完整的呈现给大家。 118 | 119 | **同时也强调虽然map是万能的,详细介绍了什么时候用数组,什么时候用set**。 120 | 121 | 相信通过这个总结篇,大家可以对哈希表有一个全面的了解。 122 | 123 | 124 | 125 | 126 | 127 | 128 | ----------------------- 129 |
130 | -------------------------------------------------------------------------------- /problems/知识星球精选/非科班2021秋招总结.md: -------------------------------------------------------------------------------- 1 | 2 |

3 | 4 | 5 | 6 | 7 | # 非科班,收获满满! 8 | 9 | 九月份悄然已过,秋招已经快接近尾声了,星球里已经纷纷有录友开始写这次的秋招总结。 10 | 11 | 其中一位录友写的很好,所以想分享出来 给公众号上的录友也看一看,相信对大家有所启发,特别是明年要找工作的录友,值得好好看一看。 12 | 13 | 这篇总结首发在代码随想录[知识星球](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ)上,立刻就获得了60个赞,很多评论,我这里放出一个截图: 14 | 15 | ![](https://code-thinking-1253855093.file.myqcloud.com/pics/20210929220903.png) 16 | 17 | 以下是星球上该录友的总结: 18 | 19 | -------------------- 20 | 21 | 211本硕非科班菜鸡转码不到一年,从最开始的迷茫到后面认识到差距的焦虑再到后面逐渐恢复坦然的心态,一路起起伏伏,但也算连滚带爬的趟了过来,**感激一路上耐心为我答疑解惑的各路大佬,尤其是咱们卡哥哈哈**。 22 | 23 | 秋招收获如下(按收到意向顺序): 24 | 25 | * 诺瓦星云 西安 软件开发工程师 提前批意向书 26 | * 字节跳动 抖音客户端开发工程师 提前批意向书 27 | * 滴滴 网约车部门后端开发工程师C++/Go 提前批意向书 28 | * 腾讯 IEG光子工作室技术中心测试开发 正式批意向书 29 | * 美团 基础研发平台后端开发工程师JAVA 正式批意向书 30 | * 阿里 阿里云计算平台后端开发工程师C++ 正式批意向书 31 | 32 | 被终结的岗位: 33 | * 蔚来 提前批后端三面挂 34 | * 百度/京东 后端提前批无音讯,正式批笔试我就都拒了 35 | * 网易 正式批一面过,但感觉不喜欢,二面就放弃了 36 | * 虾皮 提前批二面挂(北京hc太少,卷不动,秋招甚至直接不放岗) 37 | * 蓝湖 提前批二面挂(面完字节三面之后半个小时紧接着蓝湖二面,字节面了两个小时,人都麻了,强烈建议大家面试不要排太挤!!) 38 | * 招银网络 正式批一面过,二面放弃 39 | * 商汤、oppo、知乎 提前批简历挂,后面懒得投了 40 | 41 | # 秋招历程 42 | 43 | ## 开始准备 44 | 45 | 最开始的准备是从**去年十月份左右开始**,那个时候刚开始意识到自己将来找工作的问题,就选择了一门自己相对来说有一些基础的C++开始入手学习,看到网上的很多经验都说语言不是最大的问题,能学好一门后面转型都很快,所以并没有在这个问题上有什么纠结,大家看我拿到的岗位也可以发现事实确实如此。 46 | 47 | **从十月份开始看C++ Primer这本书**,断断续续花了三个多月,确实拉胯。 48 | 49 | 当时主要是事情太多,而且我在熟悉完主要的语法和特性之后,大概一个月的时间吧,就开始上手刷leetcode了,入门真的很痛苦,递归啥的看一遍忘一遍,一天吭哧吭哧弄下来也就两三道题,还基本都不是自己写出来的,因为我光理解别人的方法就需要很长时间。 50 | 51 | **后面刷题解刷到了卡哥,着实幸运,跟着卡哥的题解我也逐渐有了自己的方法模式和比较规范的代码风格**,所以到后面尽管有时候会发现也会有比卡哥更好的方法,我还是愿意先上手走一遍卡哥的思路,之后再补充别的。 52 | 53 | **不得不说,题解能跟住一个人确实很有必要**,有的题卡哥没有出题解,我也是先找到之前卡哥类似的题目找思路,再自己写出来。整个刷题的流程持续到过年,我就开始刷剑指offer了,基本简单题都可以撕,中等困难的还是只能看题解。 54 | 55 | 我个人的经验是不愿意在思考题解上浪费太多时间,**如果打眼一看就知道自己不太可能做出来,我会选择直接看题解**,省下的时间哪怕自己多敲两遍也比对着屏幕发呆效率高,毕竟面试考察的不是你创造算法的能力,会用就行了,当然这只是个人见解,大佬息怒。 56 | 57 | 刷完剑指offer大概花了半个月的时间,**时间也来到了三月份**,周围的不少人已经开始找春招实习,但更多的人还是和我一样,由于各种原因没法去找实习。 58 | 59 | 这个时候各种情绪都会有,焦虑,迷茫,没办法,改变不了现实情况只能尽可能的提升自己。 60 | 61 | 这个时候我的算法已经比较熟练了,基本一天不用太多时间也能过四道题,尽管其中仍有不少是对着题解敲的,但是对别人思路的理解确实已经练得轻车熟路了,我觉得这也是一种进步吧。 62 | 63 | **四月份开始准备项目**,没错,就是烂大街的webserver,大家都知道这个项目烂大街,但是经过后面的各种面试我也发现,不管你是什么项目,对于面试官来说都很基础。 64 | 65 | 哪怕是大厂实习的人又有几个能接触到核心,当然这也是对大部分人说的,实习大佬勿喷。**所以面试考察的就是你对基础的掌握**,就算你讲了项目各种高大上的方法,虽然可能有加分,但也是在给自己埋坑。 66 | 67 | 比如面试官可能问你有没有看过这个技术具体实现源码等等。 68 | 69 | **把自己捧的越高,一旦被发现基础有漏洞,摔得也越惨**,面试官对每个人都会有一个心理预期,比如我可能就因为非科班占了一些心理预期比较低的便宜,也就是不容易让对方失望,客户端我0基础,测开0基础,但是都过了,当然像我这样的坏处就是offer大概率只是白菜,所以综合来看有利有弊,大家自己权衡。 70 | 71 | 72 | **搞这个webserver连带各种计网,操作系统的学习花了两个月的时间**。之后便开始了面向面经自习的流程。 73 | 74 | 这个时候算法题基本不再做新的了,力扣累计刷题已经接近400,我知道里面不少题就算再拿给我,我也不一定会做,所以做新题有什么意义呢,能把之前的高频题,热题刷好就已经超过很多人了。 75 | 76 | 因为之前做题都是自己按标签做,后面看到卡哥出了系列题解,基本都是我之前做过的,所以**花了一周左右就把卡哥的pdf全过了一遍,帮助很大**。 77 | 78 | ## 提前批 79 | 80 | **后面六七月份的提前批我参与的不是特别积极**,和大多数人一样,我也总想着自己还没准备好,但是总得跨出第一步,所以就先找了一些小厂练手。 81 | 82 | 不过牛客上投的小厂基本都没有音讯,真正想投递还是官网最靠谱。 83 | 84 | 诺瓦是我的第一份offer,所以尽管我大概率去不了,我依然心怀感激,**因为经历过的人都知道第一份offer对于一个迷茫的秋招生来说是多么的宝贵**。 85 | 86 | 后面拿到字节和滴滴我着实没有想到,因为感觉自己的表现还有待提升,但能过肯定是开心的。 87 | 88 | **提前批没有笔试,所以七月份的提前批窗口确实非常宝贵**。 89 | 90 | ## 正式秋招 91 | 92 | 八月份之后就比较正常了,基本就是笔试,面试等等,**可以分享的一点是腾讯、阿里这种大厂不是特别看重笔试**,因为很多人在笔试之前就走完面试流程了,但是对于有一些劣势的同学还是希望能认真对待笔试,争取让自己多一个闪光点。 93 | 94 | 后期的算法题主要都集中在高频题、热题上面,所以还是应该把剑指刷好,配合别人分享的面经来巩固,**卡哥的算法pdf可以多看多复习**,就算没有考到也会让自己安心一些。 95 | 96 | 同时对于基础知识的整理更多的应该从面经中获取,我个人秋招下来总共看了得有至少500份面经,其实别人的面经和自己面试没啥区别。 97 | 98 | 同时也因为看了太多的面经,我自己的面经就不需要太多的整理了,除了一些没答上来的关键问题,因为基本都被之前的涵盖了,所以与其海投参加一些不靠谱的面试,倒不如整理十份面经来得实在。 99 | 100 | 参加面试主要是锻炼临场的心态,但是大厂和小厂的面试确实是有区别的,所以大厂的面经一定要多看多整理。 101 | 102 | 103 | ## 感想 104 | 105 | 一口气写下来就已经2000字了,最后还是多说两句,分享一点感想吧。 106 | 107 | **除了超级大佬,基本每一个秋招生都会有过迷茫,焦虑的心路历程**。 108 | 109 | 一方面我们需要认识到自己的局限性,认清现实。 110 | 111 | 另一方面也应该看到自己能改变的现实,许多人的时间真的只是在盲目的焦虑中虚耗,这是一个死循环,浪费的时间越多后面只会越焦虑,唯一的方法就是打起精神行动起来。当然也不用把自己逼的太紧,找到合适的排解方式,比如打会儿球打会儿游戏,让自己运行在一个正确的,符合自己节奏的轨道上不断前进。 112 | 113 | **面试是玄学,有些人的就是难,有些人的就是简单**,没有人能保证你每次都简单,但也不会每次都难,我们努力提升实力只是为了能创造更多机会,并在机会出现的时候把握住。 114 | 115 | 我觉得一个人最大的幸运就是付出的努力能有收获,所以我希望大家都能幸运地结束秋招,也希望我能继续不忘初心,保持谦逊。秋招只是人生的一段小插曲,未来的路还有很长很长,写下这篇流水账结束我的秋招,也希望能与诸君共勉,加油! 116 | 117 | 118 | -------------------------------------------------------------------------------- /problems/哈希表理论基础.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 |

参与本项目,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!

6 | 7 | 8 | 9 | ## 哈希表 10 | 11 | 首先什么是 哈希表,哈希表(英文名字为Hash table,国内也有一些算法书籍翻译为散列表,大家看到这两个名称知道都是指hash table就可以了)。 12 | 13 | > 哈希表是根据关键码的值而直接进行访问的数据结构。 14 | 15 | 这么这官方的解释可能有点懵,其实直白来讲其实数组就是一张哈希表。 16 | 17 | 哈希表中关键码就是数组的索引下标,然后通过下标直接访问数组中的元素,如下图所示: 18 | 19 | ![哈希表1](https://img-blog.csdnimg.cn/20210104234805168.png) 20 | 21 | 那么哈希表能解决什么问题呢,**一般哈希表都是用来快速判断一个元素是否出现集合里。** 22 | 23 | 例如要查询一个名字是否在这所学校里。 24 | 25 | 要枚举的话时间复杂度是$O(n)$,但如果使用哈希表的话, 只需要$O(1)$就可以做到。 26 | 27 | 我们只需要初始化把这所学校里学生的名字都存在哈希表里,在查询的时候通过索引直接就可以知道这位同学在不在这所学校里了。 28 | 29 | 将学生姓名映射到哈希表上就涉及到了**hash function ,也就是哈希函数**。 30 | 31 | ## 哈希函数 32 | 33 | 哈希函数,把学生的姓名直接映射为哈希表上的索引,然后就可以通过查询索引下标快速知道这位同学是否在这所学校里了。 34 | 35 | 哈希函数如下图所示,通过hashCode把名字转化为数值,一般hashcode是通过特定编码方式,可以将其他数据格式转化为不同的数值,这样就把学生名字映射为哈希表上的索引数字了。 36 | 37 | ![哈希表2](https://img-blog.csdnimg.cn/2021010423484818.png) 38 | 39 | 如果hashCode得到的数值大于 哈希表的大小了,也就是大于tableSize了,怎么办呢? 40 | 41 | 此时为了保证映射出来的索引数值都落在哈希表上,我们会在再次对数值做一个取模的操作,就要我们就保证了学生姓名一定可以映射到哈希表上了。 42 | 43 | 此时问题又来了,哈希表我们刚刚说过,就是一个数组。 44 | 45 | 如果学生的数量大于哈希表的大小怎么办,此时就算哈希函数计算的再均匀,也避免不了会有几位学生的名字同时映射到哈希表 同一个索引下标的位置。 46 | 47 | 接下来**哈希碰撞**登场 48 | 49 | ### 哈希碰撞 50 | 51 | 如图所示,小李和小王都映射到了索引下标 1 的位置,**这一现象叫做哈希碰撞**。 52 | 53 | ![哈希表3](https://img-blog.csdnimg.cn/2021010423494884.png) 54 | 55 | 一般哈希碰撞有两种解决方法, 拉链法和线性探测法。 56 | 57 | ### 拉链法 58 | 59 | 刚刚小李和小王在索引1的位置发生了冲突,发生冲突的元素都被存储在链表中。 这样我们就可以通过索引找到小李和小王了 60 | 61 | ![哈希表4](https://img-blog.csdnimg.cn/20210104235015226.png) 62 | 63 | (数据规模是dataSize, 哈希表的大小为tableSize) 64 | 65 | 其实拉链法就是要选择适当的哈希表的大小,这样既不会因为数组空值而浪费大量内存,也不会因为链表太长而在查找上浪费太多时间。 66 | 67 | ### 线性探测法 68 | 69 | 使用线性探测法,一定要保证tableSize大于dataSize。 我们需要依靠哈希表中的空位来解决碰撞问题。 70 | 71 | 例如冲突的位置,放了小李,那么就向下找一个空位放置小王的信息。所以要求tableSize一定要大于dataSize ,要不然哈希表上就没有空置的位置来存放 冲突的数据了。如图所示: 72 | 73 | ![哈希表5](https://img-blog.csdnimg.cn/20210104235109950.png) 74 | 75 | 其实关于哈希碰撞还有非常多的细节,感兴趣的同学可以再好好研究一下,这里我就不再赘述了。 76 | 77 | ## 常见的三种哈希结构 78 | 79 | 当我们想使用哈希法来解决问题的时候,我们一般会选择如下三种数据结构。 80 | 81 | * 数组 82 | * set (集合) 83 | * map(映射) 84 | 85 | 这里数组就没啥可说的了,我们来看一下set。 86 | 87 | 在C++中,set 和 map 分别提供以下三种数据结构,其底层实现以及优劣如下表所示: 88 | 89 | |集合 |底层实现 | 是否有序 |数值是否可以重复 | 能否更改数值|查询效率 |增删效率| 90 | |---|---| --- |---| --- | --- | ---| 91 | |std::set |红黑树 |有序 |否 |否 | $O(\log n)$|$O(\log n)$ | 92 | |std::multiset | 红黑树|有序 |是 | 否| $O(\log n)$ |$O(\log n)$ | 93 | |std::unordered_set |哈希表 |无序 |否 |否 |$O(1)$ | $O(1)$| 94 | 95 | std::unordered_set底层实现为哈希表,std::set 和std::multiset 的底层实现是红黑树,红黑树是一种平衡二叉搜索树,所以key值是有序的,但key不可以修改,改动key值会导致整棵树的错乱,所以只能删除和增加。 96 | 97 | |映射 |底层实现 | 是否有序 |数值是否可以重复 | 能否更改数值|查询效率 |增删效率| 98 | |---|---| --- |---| --- | --- | ---| 99 | |std::map |红黑树 |key有序 |key不可重复 |key不可修改 | $O(\log n)$|$O(\log n)$ | 100 | |std::multimap | 红黑树|key有序 | key可重复 | key不可修改|$O(\log n)$ |$O(\log n)$ | 101 | |std::unordered_map |哈希表 | key无序 |key不可重复 |key不可修改 |$O(1)$ | $O(1)$| 102 | 103 | std::unordered_map 底层实现为哈希表,std::map 和std::multimap 的底层实现是红黑树。同理,std::map 和std::multimap 的key也是有序的(这个问题也经常作为面试题,考察对语言容器底层的理解)。 104 | 105 | 当我们要使用集合来解决哈希问题的时候,优先使用unordered_set,因为它的查询和增删效率是最优的,如果需要集合是有序的,那么就用set,如果要求不仅有序还要有重复数据的话,那么就用multiset。 106 | 107 | 那么再来看一下map ,在map 是一个key value 的数据结构,map中,对key是有限制,对value没有限制的,因为key的存储方式使用红黑树实现的。 108 | 109 | 其他语言例如:java里的HashMap ,TreeMap 都是一样的原理。可以灵活贯通。 110 | 111 | 虽然std::set、std::multiset 的底层实现是红黑树,不是哈希表,但是std::set、std::multiset 依然使用哈希函数来做映射,只不过底层的符号表使用了红黑树来存储数据,所以使用这些数据结构来解决映射问题的方法,我们依然称之为哈希法。 map也是一样的道理。 112 | 113 | 这里在说一下,一些C++的经典书籍上 例如STL源码剖析,说到了hash_set hash_map,这个与unordered_set,unordered_map又有什么关系呢? 114 | 115 | 实际上功能都是一样一样的, 但是unordered_set在C++11的时候被引入标准库了,而hash_set并没有,所以建议还是使用unordered_set比较好,这就好比一个是官方认证的,hash_set,hash_map 是C++11标准之前民间高手自发造的轮子。 116 | 117 | ![哈希表6](https://img-blog.csdnimg.cn/20210104235134572.png) 118 | 119 | ## 总结 120 | 121 | 总结一下,**当我们遇到了要快速判断一个元素是否出现集合里的时候,就要考虑哈希法**。 122 | 123 | 但是哈希法也是**牺牲了空间换取了时间**,因为我们要使用额外的数组,set或者是map来存放数据,才能实现快速的查找。 124 | 125 | 如果在做面试题目的时候遇到需要判断一个元素是否出现过的场景也应该第一时间想到哈希法! 126 | 127 | 128 | 129 | 130 | ----------------------- 131 |
132 | --------------------------------------------------------------------------------