Coder Social home page Coder Social logo

algorithm006-class02's Introduction

极客大学「算法训练营第6期 - 2 班」作业提交仓库

讲师课件下载地址

请大家通过该链接查看讲师课件并进行下载:链接:https://pan.baidu.com/s/14kX8vGP4_0lMyC9FaBu8Tw 密码:31zj

仓库目录结构说明

  1. Week_01/ 代表第一周作业提交目录,以此类推。
  2. Week_01/G20200343030089代表学号为 089 的学员第一周的作业提交目录,以此类推。
  3. 每个目录下面均有一个 NOTE.md 文档,你可以将自己当周的学习心得以及做题过程中的思考记录在该文档中(该项不属于作业内容,是可选项)。

作业提交规则

算法题作业的提交

  1. 先将本仓库 fork 到自己的 GitHub 账号下。
  2. fork 后的仓库 clone 到本地,然后在本地新建、修改自己的代码作业文件,注意: 仅允许在和自己学号对应的目录下新建或修改自己的代码作业。作业完成后,将相关代码 push 到自己的 GitHub 远程仓库。
  3. 提交 Pull Request 给本仓库,Pull 作业时,必须备注自己的学号(取后三位)和提交第几周的作业,如089-Week 02,是指学号为G20200343030089的学员提交的第二周的算法题作业。
  4. 代码文件命名规则:**LeetCode_题目序号_学号,比如学号为 089 的学员完成 LeetCode_33_108 的第 2 题 后,请将代码文件名保存为 LeetCode_2_089.py (假设你使用的是 Python 语言)。
  5. 务必按照Pull Request的备注形式和作业文件的命名进行提交,班主任会严格按照命名形式统计大家的作业。

学习总结的提交

  1. 除代码作业外,我们要求学员每周提交一篇当周的学习感想,直接发一个独立的 issue 即可,issue 标题格式为【学号-周】总结题目】。例如【089-Week 03】二叉树的更多理解是指学号089的学员提交的第三周的学习总结。可参考:#1

Review 与点评

  1. 我们要求学员每周至少Review并点评其他5位同学的作业,点评直接回复在代码作业或学习总结下面都可。

注意事项

  1. 作业公布地址: 我们会在置顶的 issue 中公布当周的算法练习题以及其他注意事项。
  2. 如果对 Git 和 GitHub 不太了解,请参考 Git 官方文档 或者极客时间的《玩转 Git 三剑客》视频课程。从来没用过github的学员看这里的git_quick_guide,或许会对你有帮助奥。https://github.com/algorithm004-01/algorithm004-01/tree/master/Utils

algorithm006-class02's People

Contributors

1530426574 avatar a947000098 avatar armeria-program avatar blackdogcat avatar dong447943530 avatar dwgeneral avatar encodedstar avatar gdhucoder avatar hinatahoshino avatar insistgang avatar junyang0456 avatar kelly422 avatar khantiinnaraka avatar lifestyle2016 avatar liuxushengxian avatar loveindazhou avatar lsyulong avatar luobolin avatar m-li8 avatar maxminute avatar ping5626 avatar seedtyx avatar thisnull avatar wdlcoke avatar wendraw avatar xiaozhoulove avatar xkx9431 avatar yiyi8128 avatar yuqianl0923 avatar zhaojing99 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

algorithm006-class02's Issues

[514-Week1] 学习总结

使用英文是想锻炼使用英文描述技术问题的能力

Before learning the lecture, I have already finished around 150+ quizes in Leetcode, but most of them are on the level of easy or medium. However, after the first week training, i tried to challenge some hard questions such as "41. First Missing Positive" by following the tips from the teacher and found more confidence.

In the processing of solving question 41, firstly, I got the idea of using a fixed array whose length is the maximum number in the input array, which should be a working solution basicly, but it can not pass the test case when the input array is [MAX_INTEGER]. In the following, I read the offical answer and got the inspiration that it is enough to build the fixed array as the length of the input array. Finally, I addressed the case and it's even briefer than the offical one.

For more details, you can check the code. Looking forward to any suggestions

【438-week1】第一周学习总结

第一周的学习不光是了解基础的数据结构,还通过习题了解了一些基本的解题**:
1.在解题前需要明确题目要求和边界
2.针对一时没有头绪的题目,可以先思考暴力解法,或者先写几个步骤以寻找规律/重复子,如爬楼梯题目一开始毫无头绪,但写到第三层或第四层之后就发现逻辑其实很简单
3.代码和逻辑的简洁程度与程序的效率/时间复杂度并不等价,如移动0可以在Python中通过仅4行代码完成,但由于remove操作为O(n)的时间复杂度,实际效率并不高
4.在做习题的过程中偶尔会出现知道该用哪一种算法却无法完成解题的情况,因此仅仅了解算法概念并不能保证能够用代码进行实现,对于不熟练的算法还需要多次重复练习。

学习笔记:
一、 数组、链表、跳表的基本实现和特性

  1. 数组(array)
    i. 优点:计算机内存中连续地址,访问其中任何一个元素的耗时一样,时间复杂度为O(1)
    ii. 缺陷:增加元素会需要将该位置及后续元素进行群移,时间复杂度为O(N)
  2. 链表(linked list)
    i. 适用修改,增删比较频繁的情况
    ii. 元素由class/node定义,有2个成员变量value和next(指向下一个元素)
    iii. 只有一个next指针为单链表,同时还有prev指针则为双向
    iv. 头指针为head,尾指针为tail,最后一个元素的next指针一般指向空,但也可以指回head,即为循环链表
    v. 优点:增加元素只需前继节点的指针指向新元素,新元素的指针指向后续节点,时间复杂度为O(1)
    vi. 缺陷:访问链表中间的元素需要从头节点开始依次,时间复杂度为O(n)
    vii. 工程应用:LRU cache
  3. 跳表(skip list)
    i. 通过升维(空间换时间)改善链表lookup的缺陷
    ii. 对链表增加一级索引,每次移动next+1(跨2个元素),二级索引则跨4个元素
    iii. 根据元素个数增加log2n个级索引,时间复杂度为O(logn)
    iv. 缺陷:维护成本较高,增加删除元素需要更新全部索引,的时间复杂度为O(logn)
    v. 空间复杂度为O(n)
    vi. 工程应用Redis

【026-week1】利用五遍刷题法来学习算法

在看视频以及做题的过程中,意识到了五遍刷题法确实能够让自己了解到各种解法并进行优劣对比。因此总结一下五遍刷题法的具体操作

第一遍

  1. 选择要做的题
  2. 花 5~15 分钟理解题目意思以及思考题目可能的多种解法
  3. 如果有思路就写代码来实现;如果没有思路,马上查看已有的多种优秀解法,而且要背诵和默写这些解法 (没有思路就一定要查看解法,不要浪费时间纠缠题目)

第二遍

  1. 在背诵了多种解法思路后,自己不看代码来实现解法 (如果有 Bug 就修改到通过为止)
  2. 在实现了多种解法后,比较不同解法的执行时间和内存消耗,对比找出哪种解法更优秀,为什么会更优秀 (比较时最好更加关注执行时间的消耗)

第三遍

  1. 过了 24 小时后,重新做一遍前一天做过的题目
  2. 找出自己不熟练的题目和解法,进行专项训练 (不知道视频里面说的专项训练指的是重复多次背诵不熟练的解法,还是说找其他的与不熟练的题目类似的题目来训练)

第四遍

  1. 过了一周之后,重新做一遍上一周做过的题目
  2. 找出自己不熟练的题目和解法,进行专项训练

第五遍

  1. 如果有面试的话,在面试前进行恢复性训练。也就是重新做一遍之前已经做过的题目
  2. 如果觉得准备得不够就在面试的前几周进行恢复性训练,以便有足够的时间来准备面试 (总之根据自己的时间和是否准备充分来决定什么时候开始恢复性训练)

【450-week 01】第一周学习总结

  1. 老师的算法视频课基本学习过一遍,接下来会继续看第二遍;
  2. 看视频课的方法,很有收获,靠自己工作外自学,时间精力有限,很难这么快领悟到;
  3. 有时间,继续找机会“练掌”。
  4. 算法优化的过程中有意思。

算法训练营(第六期)第一周作业

要求

  1. 每周从覃超老师布置的题目中,至少完成并提交两道算法题
  2. 围绕每周重点学习的算法知识点,撰写一篇有观点和思考的技术文章或总结,切忌流水账。

作业提交 Deadline

2020年2月16日 23:59 (以当地时间为准)
未按时提交作业,会在个人作业总分中 -3 分

截至毕业,每缺一周学习总结,-5 分
截至毕业,每缺一周代码作业,-9 分

本周作业概述

本周需要完成学习的视频内容:

  • 第 3 课 | 数组、链表、跳表
  • 第 4 课 | 栈、队列、优先队列、双端队列

以上两课视频后,覃超老师都给出了大家可以练手的算法题。

其中,第 4 课的课后作业(第2节视频后)还包括:

  • 用add first或add last这套新的API改写Deque的代码
  • 分析Queue和Priority Queue的源码

请大家将此部分作业,放在本周学习总结中一并提交

本周算法习题库:

第三课课后习题:

https://leetcode-cn.com/problems/remove-duplicates-from-sorted-array/
https://leetcode-cn.com/problems/rotate-array/
https://leetcode-cn.com/problems/merge-two-sorted-lists/
https://leetcode-cn.com/problems/merge-sorted-array/
https://leetcode-cn.com/problems/two-sum/
https://leetcode-cn.com/problems/move-zeroes/
https://leetcode-cn.com/problems/plus-one/

第四课课后习题:

https://leetcode.com/problems/design-circular-deque
https://leetcode.com/problems/trapping-rain-water/
用add first或add last这套新的API改写Deque的代码
分析Queue和Priority Queue的源码

改写代码和分析源码这两项作业选做,需要在你的本周学习总结中一并提交。

【036-week 01】学习总结

python

熟悉了list slice
一直看的多,写的少,写起来除了理解算法还要看py语法,挺好。

【556-week 01】第一周学习总结

学习内容:
本周学习了数组、链表、跳表、栈、队列(双端队列,优先队列),及其相关操作的时间复杂度。

优化**:升维,以空间换时间

学习思维:过遍数

本周不足:
跳表和优先队列还没有很好地理解。
关于栈和队列的题目还在思考中,进展缓慢。
链表的实战题目忘做了。
前几天比较有干劲做得比较多,后面几天放松了,导致没法完全全部作业。

本周收获:
至少对代码的驾驭能力有一点提升了,一开始看到代码都有点懵,做菀过几小时重新做又没有印象了。虽然现在依然很难记住做过的题目,但复习上手的速度有了明显的改善,特别是对于数组的题目,但关于栈的问题还没有怎么上手的感觉。

本周教训:
下周的学习要加倍努力了,这周还是太懒散了。

【386-week 01】对于本周学习过程的总结

1、课程方面
本周主要讲述了数组、栈、队列,各有千秋,适应场景不同。
数组:
在内存中需要占用连续空间;
插入与查询快,常数级复杂度。删除慢,需要移动数据;
适用于需要随机访问的场景。
栈:
先进后出;
增加与删除时间复杂度为:O(1),查询为:O(n);
适用于最近相关性问题,以及算法中常用多个栈解决存储特殊值、实现队列等问题
队列:
先进先出;
增加与删除时间复杂度为O(1),查询为:O(n);
适用于滑动窗口问题。
我们常用的队列是:Deque(双端队列)、Priority Queue(优先队列)

2、算法方面:
对于算法题的解决思路上有了新的收获,在遇到不会的算法题时需,可以重新思考,大致分为这几步:

  1. 暴力法:用最笨的方式解决问题
  2. 最简单场景法:对于问题,先设想如果是最简单的场景的话应该怎样做,然后再推广到复杂环境
  3. 常规技巧法:通过学习其他同学的解法,自己模仿写出代码,并理解解题思路
  4. 最优解:在国际站看大神的解法,用最少的代码写出漂亮的解法
    对于“五毒神掌”的使用上,觉得还需要增加些时间反复多写几遍。五遍其实不足以让自己记住一些算法的实现方式,还需要重复更多次的练习,这需要时间的积累才可以。

3、源码方面:
在阅读源码上以前总是有误解,以为是需要一行一行研读的。但是现在是觉得,对于源码层面来说,主要掌握其自身属性与方法才是最重要的。需要知道其每个方法的使用场景以及是否有特殊的返回值处理,都是需要了解的。
再有就是需要了解其本身的数据结构与关键方法用到的算法都有哪些,需要将这些记录并背下。不论是面试还是工作中,这部分原理都是最有用的。

【578-week1】第一周学习感受

  • 五毒神掌:刷题要刷 5 遍
  • 空间换时间的优化思路
  • 遇到难题,先考虑能否暴力求解,然后再优化。或者从基本情况开始,寻找重复子结构,从而获得解题思路。

【548-Week01】学习总结

五毒神掌很有道理,但是目前来说还未做到,主要是第一遍自己使劲想耽误太长时间,希望在接下来的学习过程中客克服这个心理难关。算法中讲到这个升维**太厉害了,以空间换时间,忽然明白不管是编程还是干别的事,指导**很重要。
下面是使用addFirst或者addLast来改写老师在第二节课上写的代码:
//addFirst
Deque first = new LinkedList();
first.addFirst("a");
first.addFirst("b");
first.addFirst("c");
System.out.println(first);

    String firstStr = first.getFirst();
    System.out.println(firstStr);
    System.out.println(first);

    while(first.size() > 0){
        System.out.println(first.removeFirst());
    }
    System.out.println(first);

【566-week01】学习总结

知识概括小细节:
1> 数组是一种线性数据结构,用连续的存储空间存储相同类型数据
2>连续的内存空间、相同的数据,所以数组可以随机访问,但对数组进行删除插入,为了保证数组的连续性,就要进行数据迁移工作
数组支持随机访问,根据下标的随机访问时间复杂度是O(1)
3>链表的内存结构是不连续的内存空间,是将一组零散的内存块串联起来,从而进行数据存储的数据结构。
每一个内存块被称为节点Node。节点除了存储数据外,还需记录链上下一个节点的地址,即后继指针next
4>链表的插入删除数据时间复杂度为O(1),随机访问的效率为O(n),和数组相比,链表的内存消耗较大,每个存储节点都需要额外的空间存储next指针地址
5>双向链表,节点除了存储数据外,还有两个指针分别指向前一个节点地址(前驱指针prev)和下一个节点地址(后继指针next),首节点的前驱指针prev和尾节点的后继指针均指向空地址
6>栈,后进先出
7>队列,先进先出,操作受限的线性表,正常情况下入队和出队的时间复杂度都是O(1),如果队尾已满,进行数据搬迁,搬迁的时间复杂度是O(n),平均时间复杂度还是O(1)

分析Priority Queue 的源码:
1.PriorityQueue是一种无界的,线程不安全的队列
2.内部实现结构是数组,内部维持一个小顶堆数据结构,
3.添加节点,关键代码:int parent = (k - 1) >>> 1; 每次与父节点进行比较,小于父节点则进行结构调整,从k指定的位置开始,将x逐层与当前点的parent进行比较并交换,直到满足x >= queue[parent]为止。
4,删除节点的时候,关键代码:int child = (k << 1) + 1;,如果是最后一个元素,则直接删除,如果不是最后一个节点,则要进行siftDown结构调整,从k指定的位置开始,将x逐层向下与当前点的左右孩子中较小的那个交换,直到x小于或等于左右孩子中的任何一个为止

【614-week01】学习总结

初入算法训练营,一切都还在熟悉的过程中,现总结几点体会:
1.“三天不念,口生,三天不做,手生”,要想修炼一门技术,勤学苦练是根本,来到算法训练营就是为了督促自己,切莫“三天打鱼,两天晒网”。
2.原来写代码不怎么重视数据结构,听了覃超大神的讲解,自己又把各种数据结构重新梳理了一遍,尤其C++中STL,包括向量、栈、队列、双端队列、优先队列、链表等等,熟悉这些才能讨论算法,这也是算法的基础。
3.优秀算法的精髓就是“少做事”!从“暴力法”到“双指针法”,其优化的方向就是找出其中重复的无用功,再在代码中新加条件将它们剔除,这就达到了优化算法的目的。

【584-week1】关于几个简单算法的理解

1.暴力法
往往通过多层循环,在内层循环中,通过某些特定约束条件,得出解;
另外,还有可能在循环结束之后处理某些特例;

暴力算法,往往时间复杂度太大,但便于理解。

2.双指针法
往往是定义两个指针,通过一次遍历,同时从两端对各个元素进行检查;
每次循环结束,会根据条件更新其中一个指针;
结束条件往往是当两个指针指向同一个元素时;

3.其他
暴力算法往往可以进行优化,至少时间复杂度可以优化;
双指针算法在时间复杂度上往往是接近最优解;

【498-week 01】第一周总结

​ 在课程中,超哥一直在重复强调刷题要刷多遍,刷题最大的误区就是只刷一遍。这让我想到高三刷数学题,每天都在刷,刷完一张试卷,老师讲解,自己总结,到最后每种类型的题目都要做到:看到题目就知道解法是怎么样。

​ 我觉得五毒神掌的目的绝不是让我们刷五遍题,而是让我们掌握每个题目的解法,掌握到看到题目后立马就能想到对应的解法,和高考刷题目的是一样的。所以五毒神掌是否为最后一掌的判断依据,应该是从开始code到结束code,编码大致匀速,没有大的卡顿,且调试一两遍内就能通过。

​ 当然,理解远比死记硬背来的高效,因此总结各种类型解法是很重要的。解法优化中两个重要**:1. 空间换时间 2. 升维。通过这周学习和刷题,我学习到了以下几种解法:

  1. 循环遍历法,简称暴力法,大部分都可以解,常见格式:

    for i := 0; i < len(nums)-1 ; i++ {

    ​ for j := i; i < len(nums); j++ {

    ​ }

    }

  2. 循环遍历 + hash缓存法,这也是动态规划的简版,

  3. 左右双指针向中间移动。涉及最值问题等

  4. 快慢双指针,快指针全局遍历,慢指针计数

  5. 应用栈,一般存在最相关性和先进后出问题

【388-week01】学习总结week01

对五毒神掌的感悟

以前的学习就是看过一遍,就不管了,以后用的多就掌握的熟,用的少就慢慢忘了。学习了五毒神掌后发现这个招式,不仅能用于算法学习,可以用到所有学习领域,我们都不是天才,没有过目不忘,所有的一切都可以一遍遍学习,但是不能傻傻的学习。

对于本周学习的体悟

使用合理的数据结构,对于编程的提升非常大,但是要想能够合理使用数据结构和算法,需要我们对这些东西有足够的理解和使用

【634-week1】第一周小结

本周匆忙加入到训练营。没有经过预习周。一上来就开始看课程,练题了。
《异类》的这套刻意练习的方法,是目前很大的一个收获。掌握了这个方法,我觉得参加这个训练就已经很值了。至于算法学习,只是刻意练习的一次具体的应用。希望通过这次训练之后,我掌握的不仅仅是算法知识,而是一套自我训练的一般性的方法。以后在学习其他技能的时候,也可用用刻意练习的方式,比别人更快地掌握。“分解,重复,反馈”。之前没有掌握这个方法的时候,练题是无规律题海战术,浪费大量的时间没有收获。方法不对,再努力也白搭。人与人之间的竞争就是做事方式的竞争。收获很大。后面的练习,我准备个表格。记录没道题的刷题次数。确保五毒神掌能够严格执行。

【364-week1】关于伪学习的误区

伪学习的常见误区

什么叫“伪学习者”呢? 我试着下一个定义:看着挺忙,每天也花不少时间学习,但长时间下来感觉没什么提高或者提高缓慢。

具体表现如下:

  1. 没想清楚,上来就干。通过trial-and-error (试错)的方法来做LeetCode题目。看着会了,但半天也写不出ac的代码,总有bug。

  2. 学完新的工具和更好的技术,不使用。总用之前自己熟悉的那套,例如快捷键记住了么?在IDE写代码能全程不用鼠标么?ZSH配置好了没?

  3. 不复习,题目只做一遍。

  4. 心急,贪多,图快,总想一口吃个胖子。总想我还能学,我还能多做几道题。学过做过的题目不能及时复习和举一反三。

  5. 写完代码不测试。表现在直接commit,不写几个测试案例。提交错了再修改代码。

  6. solo-learning。不是“自习”的意思,而是自己独自学习,不和小伙伴或同学交流。不是不好意思就是觉得自己特牛,谁也看不上。

  7. Last but not least. 看懂了 != 理解了 != 能写出来

关于伪学习的误区,你还有什么补充的么?

【448-Week01】学习总结

作为参加过9.9元试听的学员,和试听完全重复的本周作业提交仍然是压线。。。

  1. 五毒神掌刷洗需要更多遍数。有些题目刷了3次(当天,第二天,第二周),结果这次从头写,还是要debug一会儿边界条件。可以mark一些经典题,隔段时间就刷一刷了。
  2. 千万别自己想算法。为了提高效率,刷题的时候,都是读了题干直接看题解。之前尝试过自己有思路就独立写,结果是没想那么清楚,耗时太长不划算。
  3. 一看就会一写就懵。多动手,多动手,多动手。

【398-week 01】第一周总结

关于训练营的质量,班级群里不少人都有疑问,那我总结下我的看法。
一:我是老师说的反例,之前不管是在leetcode,还是欧拉计划(https://projecteuler.net/https://projecteuler.net/),我比较死磕,结果常常一道题目搞一天,导致总共做了十几道题就搁浅了。
二:按照老师的方法,其实我内心是不安的,因为长期的信条是要自己先思考。但是我知道老师的方法是对的,在工作中领导也强调刻意训练,肌肉记忆,当时的例子是写讲话稿子。我们还要克服一个灾难,觉得懂了,不能熟练写出,也就是基本功;我学习大学数学的例子,导数我学会了,但是大学不像初中高中大量的刷题巩固,导致我后面看积分,老是要复习导数的概念;工作后一年,微积分全忘了,但是辅导亲戚高中数学还绰绰有余。
三:不要忽视刻意联系的重要性,不要忽视习惯的重要性。这是我报训练班的目的,借鉴别人的经验,大家互相监督(没有强制性的监督,对我挺危险的)。
四:不做自以为是的“聪明学生”,做刻意练习,循序渐进的“乖学生”。
关于这周课程知识:
数组,栈,队列都比较自然,好理解;数组左右向中间夹逼,数学归纳法递推,最近相关性-stack 这三个思路很重要。
对跳表有点感觉,没看相关实现代码,对实现还是比较好奇。

516-week1 我想到的

老师讲的东西可以再工程一些,比如我们学习数组的话,大家可以思考不同的语言创建数组,链表的,栈的方法,或者自己用自己熟悉的语言,简单实现一下。 可以参考 隔壁小争哥老师的 那个project

工程上可能还需要了解更高级的 map,reduce方法, 以及 需要了解 深复制,浅复制, 那些方法是改变数组原有结构,等等吧。

第一周,感觉时间还是不够用,不过当初花钱就是为了逼迫自己,不能白花钱…… 老师讲的还是和之前的没多太多吧。 加油两个月就好

【520-week 01】学习总结

Week 01 Notes

Array

  • Time Complexity

    Operation Time Complexity
    Prepend O(1)
    Append O(1)
    Insert O(n)
    Delete O(n)
    Look up O(1)

Linked List

  • Time Complexity

    Operation Time Complexity
    Prepend O(1)
    Append O(1)
    Insert O(1)
    Delete O(1)
    Look up O(n)

Skip List

  • Time Complexity

    Operation Time Complexity
    Prepend O(1)
    Append O(1)
    Insert O(1)
    Delete O(1)
    Look up O(logn)

Stack

  • Time Complexity

    Operation Time Complexity
    Insert O(1)
    Delete O(1)
    Look up O(n)

Queue

  • Time Complexity

    Operation Time Complexity
    Insert O(1)
    Delete O(1)
    Look up O(n)

Deque

  • Time Complexity

    Operation Time Complexity
    Insert O(1)
    Delete O(1)
    Look up O(n)

Exercises

accepted index level desc url
[ x ] 26 easy 删除排序数组中的重复项 remove-duplicates-from-sorted-array
[ x ] 189 easy 旋转数组 rotate-array
[ x ] 21 easy 合并两个有序链表 merge-two-sorted-lists
[ x ] 88 easy 合并两个有序数组 merge-sorted-array
[ x ] 1 easy 两数之和 two-sum
[ x ] 283 easy 移动零 move-zeroes
[ x ] 66 easy 加一 plus-one
[ x ] 641 hard 设计循环双端队列 design-circular-deque
42 medium 接雨水 trapping-rain-water
11 easy 盛最多水的容器 container-with-most-water
[ x ] 283 easy 移动零 move-zeroes
70 easy 爬楼梯 climbing-stairs
15 hard 三数之和 3sum
[ x ] 206 easy 反转链表 reverse-linked-list
24 hard 两两交换链表中的节点 swap-nodes-in-pairs
[ x ] 141 easy 环形链表 linked-list-cycle
142 hard 环形链表II linked-list-cycle-ii
25 medium K个一组翻转链表 reverse-nodes-in-k-group
[ x ] 20 easy 有效的括号 valid-parentheses
[ x ] 155 easy 最小栈 min-stack
84 medium 柱状图中最大的矩形 largest-rectangle-in-histogram
239 medium 滑动窗口最大值 sliding-window-maximum

【430-week 01】学习方法的探索

探索

算法对于自己来说是一块困难的知识区域。如何在学习的过程中,探索到适合自己,能够建立学习的自信和乐趣的学习方式也就变得十分重要了。

  • 在这一周的学习过程中,先循序渐进的把课程里课件对应的各种数据结构去理解透彻,同时会去学习极客专栏【数据结构与算法之美】,力争做到对这些数据结构的掌握。这个过程中一定要善于去找到问题点并且去查阅资料或者请教班群,解决掉这些问题点
  • 第二个过程就是去仔细学习章节的视频教学。碰到实战题目的地方时,一定要先自己去思考,尝试去解答,这也是对上阶段知识点应用的一个检验。如果是毫无思路的情况,我会去学习视频里对题目的讲解,然后在去LeetCode上模拟实现
  • 前面的过程坚持下来后,课后作业也大都在不看题解的情况下完成了,个别题目还是没有思路或者做不出来。“五毒掌”就要应用起来了。目前对于题目的的状态也是按照五毒掌去实践的

题目

  • 本周作业
掌握 index level desc url
熟练 26 简单 删除排序数组中的重复项 remove-duplicates-from-sorted-array
熟练 189 简单 旋转数组 rotate-array
熟练 21 简单 合并两个有序链表 merge-two-sorted-lists
熟练 88 简单 合并两个有序数组 merge-sorted-array
熟练 1 简单 两数之和 two-sum
熟练 283 简单 移动零 move-zeroes
熟练 66 简单 加一 plus-one
-- 641 中等 设计循环双端队列 design-circular-deque
-- 42 困难 接雨水 trapping-rain-water
  • 课后作业
章节 掌握 index level desc url
3.4 一般 11 简单 盛最多水的容器 container-with-most-water
3.4 熟练 283 简单 移动零 move-zeroes
3.4 熟练 70 简单 爬楼梯 climbing-stairs
3.4 熟练 15 中等 三数之和 3sum
3.4 熟练 206 简单 反转链表 reverse-linked-list
3.4 熟练 24 中等 两两交换链表中的节点 swap-nodes-in-pairs
3.4 熟练 141 简单 环形链表 linked-list-cycle
3.4 熟练 142 中等 环形链表II linked-list-cycle-ii
3.4 熟练 25 困难 K个一组翻转链表 reverse-nodes-in-k-group
4.2 熟练 20 简单 有效的括号 valid-parentheses
4.2 熟练 155 简单 最小栈 min-stack
4.2 -- 84 困难 柱状图中最大的矩形 largest-rectangle-in-histogram
4.2 一般 239 困难 滑动窗口最大值 sliding-window-maximum

【638-Week_01】学习总结

很早就想把算法好好学学,遇到算法题目总是摸不着头脑。抱着试一试的态度,报名了极客大学的算法训练营。

覃超老师第一课有讲到学习方法,五遍学习法真的有效吗?从开始学习的前两天,我还是似懂非懂的感觉,有点耐不住性子了。我又回看一遍老师讲的学习方法,并告诉自己再坚持一下,经过第三天的再去练习前面学过的题目,终于能独自解出一道算法题了,内心雀跃起来。

后面再经过两天的练习,对算法题有些感觉了。一些常见的解题思路,如: 双重循环,双指针,递推。看到类似的题目,都会浮现在脑海当中。再去练习类似的题目时,发现比之前轻松了许多。至少现在能把简单的算法题目做的熟练了。

本周作业把所有的简单题目都提交了,中等,难题还需要老师,助教和同学们的指点和帮助。

谢谢极客大学能提供这样一个学习算法的平台。

【536-week1】第一周学习总结

本周学习,了解了一下跳表、优先队列、双端队列的一些数据结构,以前没使用过这些东西;
跳表,用空间换时间,查询任意数据的时间复杂度是O(logn),主要**是,建立多级索引,每级索引元素的间隔是上一级索引元素间隔的2倍,这样在定位第n个元素的时候,能大大提升查找的时间;
双端队列,Deque,既可对头元素进行操作,也可对尾元素进行操作,相当于栈和队列相加;
优先队列,可以按照自己设定的优先级对元素取数,相当于在优先队列里,元素自动进行了一次按设计要求的排序;

对于学习方法,老师最主要提到了五毒神掌,要求一道题目最少刷五遍,并且如果第一次看到题目没有思路的时候,不要去想,直接去看其他人的解法,这点很重要;

对于本周的算法题,个人感觉比较有意思的是189翻转数组的题,分为3步,(1)讲这个数组翻转一遍(2)讲0 - k-1 翻转一遍 (3) 将k - len - 1 翻转一遍,即可达到向右移k位的效果.

【560-week 01】第一周课程学习总结

学习以及练习解题过程

  1. 5-10分钟:读题和思考

  2. 有思路:自己开始做和写代码;不然,马上看题解!

  3. 默写背诵、熟练

  4. 然后开始自己写(闭卷)

数组链表跳表基本实现

  1. 数组在内存里连续所以数组访问快O(1),增加删除慢O(n).
  2. 数组空间不够会重新申请一块乘以2空间大小的内存空间,然后把数据复制过去
  3. 链表(linked list) 会定义一个class,单链表,双向链表(previous,next)
  4. 增加删除是O(1),查询是O(n)
  5. 跳表在redis应用了
  6. 优化**,升维+空间换时间,跳表就是升维+空间换时间,增加索引,时间复杂度变为O(logn),当然维护成本也会变高,相应的也会更新索引

栈和队列的实现和特性

  1. 栈先入后出
  2. 队列先入先出
  3. 两个数据结构增加删除都是O(1),查询是O(n)
  4. 优先队列,取出操作是O(logn),底层实现的数据结构较为复杂和多样:heap,bst,treap

问题

对于数组实现的栈和队列,增加删除元素为什么是O(1)的复杂度?

【404-week01】学习总结week01

学习笔记

1.思维要点记忆
算法刷题最大误区:只做一遍
复杂算法最后往往拆解成判断 循环 递归等基本操作,算法就是寻找重复单元
算法解题思路:升维

2.学习难点
对本周的数组、链表、栈、队列数据结构的理解还不够深入,以前只局限于使用类库
对于实现细节需要深入学习;
对于本周习题三数求和的推导过程还在理解中;

3.兴趣点
跳表这个以前没有了解过,感觉思路很有意思,对于redis中的实现希望能研究一下

4.感想
本来以为本周讲解的数据结构大都常见且常用,学习没有什么难度,但是学习之后发现
对于背后的实现细节知之甚少,并且只限于使用类库,如果自己动手实现有很多地方都想不到,需要深入学习。
LeetCode解题时,大都只能想到最直观的暴力解法,对于抽象的解题方式需要看了题解才明白,
还是需要像老师说的需要熟练套路。
本周因为工作原因到周六的晚上才开始进入学习,有些仓促,作业也仅做了简单的几题,对自己是个损失,后续得补上。

【426-week 01】学习总结

学习笔记

人都说,数学和计算机算法及程序是紧密结合的,但工作这么久,实话讲,没什么体会

直到最近才改变想法,源于一部美剧,《疑犯追踪》,也源于一个数列,斐波拉契数列

先说斐波拉契数列吧,F(1)=1,F(2)=1, F(n)=F(n-1)+F(n-2)(n ≥ 3,n ∈ N*)

我真的记得数学习题上有解过,这个数列可以用递归、循环、通项公式、矩阵

这真是一下了解到了,算法中的数学可以这么用

这个数列,目前不知道实际可以用在哪里,但它好像涉及到,我们所处世界的一系列“巧合”

不是巧合吧,现在我明白到,以前学的那些,好似没什么用处,但其实是我太low了...

最后附上《疑犯追踪》中的一段话

π, The ratio of the circumference of a circle to its diameter.

π,圆周长与直径之比

And this is just the beginning. It keeps on going. Forever. Without ever repeating.

这是开始,后面一直继续,无穷无尽,永不重复

Which means that contained within this string of decimals, Is every single other number.

也就是说在这串数字中,包含每种可能的组合。

Your birth date, combination to your locker, your social security number, It’s all in there somewhere.

你的生日、储物柜密码、社保号码,都在其中某处。

And if you convert these decimals into letters, you would have every word that ever existed in every possible combination.

如果把这些数字转换为字母,就能得到现有的单词及可能有的每一个单词。

The first syllable you spoke as a baby, the name of you latest crush, your entire life story form beginning to end. Everything we ever say or do... all of the world’s infinite possibilities rest within this one simple circle.

你婴儿时发出的第一个音节,你心上人的名字,你一辈子从始至终的故事,我们做过或说过的每件事,宇宙中所有无限的可能,都在这个简单的圆中。

Now what you do with that information...

用这些信息做什么

What it’s good for...

它能有什么用

Well, that would be up to you.

这取决于你们

【462-Week01】数组解题思路的一点总结

常用解题思路

单向线性扫描

从左到右顺序扫描这个数组,并使用一个哨兵来监测我们感兴趣的东西。例如leetcode的283题,就可以使用这个思路来解决问题,为便于你理解,这里我贴出283题的具体解题代码:

class Solution {
public:
    //时间复杂度是O(n)
    void moveZeroes(vector<int>& nums) {
        int iSentry = 0;        //哨兵,它始终标记的是非零元素可以被存储的位置,
        //Step1.先处理非零元素
        for(int iLoop = 0; iLoop < nums.size(); ++iLoop)
        {
            if(nums[iLoop] != 0)
            {
                nums[iSentry] = nums[iLoop];
                ++iSentry;
            }
        }
        
        //Step.2将iSentry及以后的位置都置为零
        for(;iSentry < nums.size(); ++iSentry)
        {
            nums[iSentry] = 0;
        }
    }
}

这种思路解题的时间复杂度一般是O(n)。

嵌套循环

使用嵌套循环对数组进行处理,最经典的案例应该就是冒泡排序法了。但这种解法的时间复杂度一般都比较高,粗略的说具体看你使用嵌套了几层循环。为了方便理解,这里给出冒泡排序法的实现代码:

void bubbleSort(std::vector<int> &vecInput)
{
    if(vecInput.size() <= 1)
        return;
    //外层循环的含义是,输入数组中有多少个数,就需要进行多少次冒泡
    for(int i = 0; i < vecInput.size(); ++i)
    {
        //内层循环进行冒泡操作,冒泡要执行多少次取决于还剩下多少个数是无序的,显然外层循环每进行一次就会有一个数是有序的
        for(int j = 0; j < vecInput.size() - i - 1; ++j)        //还要再减去1的原因是,索引是从0开始的,代码中有j+1这样的操作,要防止数组溢出;循环条件指明的是无序部分还剩下多少(实际上无序部分总数应该是vecInput.size() -i)
        {
            if(vecInput[j] > vecInput[j+1])
            {
                //交换位置,局部冒泡
                int iTemp = vecInput[j];
                vecInput[j] = vecInput[j+1];
                vecInput[j+1] = iTemp;
            }
        }
    }
}

这是一个O(n^2)时间复杂度的算法。

双指针

解决数组问题最基础的方法是单向扫描,在单向扫描达不到解题目的的时候,我们可能会使用嵌套循环,每一个循环又是一个单向扫描的方式来寻求问题的解。

而所谓双指针的解法,则是从数组的头部和尾部两个方向向中间收敛(夹逼)以加快处理速度的一种解决方案。它的时间复杂度是O(n)。当你需要使用嵌套循环的时候,你可以考虑一下你的问题是不是可以通过双指针的思路进行优化,如果你手写过快排算法的话,你可以发现快排,在局部上使用了双指针的思路。使用双指针进行问题求解的时候,有时需要先排序,而有的时候并不需要,这需要你进行分析。像下面的例子,刚好就是不需要排序的,针对这个例子,你排序了反而会得出错误的结论。

这里的指针只是一个抽象的用于表述数组元素位置的说法,它和C/C++语言里的指针可不一样。为了便于你理解,我这里贴出了leetcode11题使用双指针解法求解的代码:

class Solution {
public:
    int maxArea(vector<int>& height) {
        //使用嵌套循环的方式求解,时间复杂度是O(n^2)
        if(height.size() <= 1)      //不构成长方形,面积自然也无从提起了
            return 0;
        
        int iLeft = 0;      //表示那个从左往右扫描的索引
        int iRight = height.size() - 1;     //表示那个从右往左扫描的索引
        int iLength = 0;        //长、宽、面积、最大面积的变量声明只是为了减少内存分配的次数
        int iWidth = 0;
        int iArea = 0;
        int iMaxArea = 0;
        while(iLeft < iRight)
        {
            iLength = iRight - iLeft;
            iWidth = height[iRight] < height[iLeft] ? height[iRight] : height[iLeft];
            iArea = iLength * iWidth;
            if(iArea > iMaxArea)
                iMaxArea = iArea;
            //移动指针,谁小谁往它的方向上移动
            height[iLeft] < height[iRight] ? ++iLeft : --iRight;
        }
        return iMaxArea;
    }
};

常见边界条件

必须考虑的边界

不能使数组下标越界,这会造成灾难性的结果。

周总结

时间没有规划好,也完全没有预料到会如此的艰难,下周还是每天都要进行算法和数据结构知识的学习,不能把所有的事情都堆积在周末。另外按照五毒神掌的方法,周末反而应该是一个重复的时间。加油。这篇总结,是我学习视频课程的时候随手做的,如果其中有疏漏的话,欢迎支持,万分感谢。同时,欢迎你们补充我总结中缺失的地方,万分感谢。

🌟🌟🌟Week 01 算法题作业链接集合

Hi各位同学,俗话说“三人行,必有我师”,因此我们鼓励大家在整个学习期间,多多 Review 同班同学的代码并进行点评。在这个过程中:

  1. 可能你会从其他同学的代码中学到一个更优的思路
  2. 可能你会因为其他同学给你的评论启发新的灵感
  3. 可能你的代码会得到大家纷纷的点赞
  4. 有时候也可能因为其他小伙伴的一句“学习了”而备受鼓舞

“让优秀的人一起学习”,大家可以在互相 Review 的过程中思考更多、获得更多。因此,请把你的算法题作业链接(你自己仓库的链接就好)回复在下面,这样大家就可以更方便的进行代码 review 啦!

跟帖格式:

学号后三位:
姓名(你在班里的姓名,便于同学可以跟你讨论):
你使用的语言:
你的代码链接:

【508-week 01】第一周学习总结

学习方法:
五遍刷题法:
1.5-15分钟:读题+思考
a:无思路:直接看解法:注意!多看几种解法,理解背诵默写
b:有思路:直接做
2.无提示,写出来
3.一天后再做一遍
4.一周后再做一遍
5.一个月后再做一遍
6.面试前1-2周在复习一遍

代码风格:
参考:google code style

日常思考方式:
自顶向下思考方式
1.考虑主干,摒弃细节
2.细节局部实现

【622 Week01】一些感想

初次加入算法训练营,对练习的流程还不是特别熟悉,后面继续改进。

  • 数据结构和算法这个课程,我自己从高中开始就有接触了,也参加过算法竞赛,但直到现在在这方面也没什么建树。归其原因,没有什么兴趣。对于这种做题类型的课程,可以说是不擅长,也没有动力。但现实所迫,不得不学习。参加这个培训课程,也算是对自己的督促。
  • 这一周通过做一些题目,也充分了解了刷题的过程(五步刷题法),效果也是有的。希望自己在后面的学习过程中能够坚持下来,如果有可能的话,也能深入地学习这方面的内容,争取在工程项目中有所运用。

【496-week 01】数组算法-总结

001 今天主要练习量删除数组中的重复项和旋转数组两个算法,都是我之前没有遇到的解题思路,没上课之前我没有时间复杂度和空间复杂度,所以在做关于列表的算法题时,只会简单粗暴,尤其是还经常会插入和删除操作,这些都会增加时间复杂度。

002 今天了解了在进行数组(list)操作时,要善用她的随机访问属性,要避免使用它的增删插入操作,减少时间复杂度。

003 同时今天了解了顶级编程人员都是怎么练习了,尤其是五毒神掌,让我受益匪浅,让我知道自己过去练习量是不够的的,至少不够5遍,所以每次遇到算法题都感到心虚。

004 希望在接下的时间能跟老师一起进步,熟练掌握五毒神掌,让自己的算法水平处于顶尖水平。

[382-Week-01] 学习总结

学习算法重要方法
切题四件套:
1、反复审题、确认理解的正确
2、考虑多种解法 比较不同接法的时空 复杂度 找出最优解
3、coding
4、列举几个测试样例

五毒刷题法
第一遍:5-10分钟的读题加思考、直接看解法多解法、背诵、默写好的解法
第二遍:空白文件默写->leetcode提交->通过
第三遍:过一天后,再重复之前做的题
第四遍:一周后重新做做过的题
第五遍:面试前恢复训练

优化的重要**:升维、空间换时间

数组Array 的时间复杂度: 插入、删除0(n) 查询复杂度O(1)
链表linked list 的时间复杂度:插入、删除O(1) 查询O(n)
栈stack 的时间复杂度:添加 删除O(1) 查询O(n)
队列Queue 的时间复杂度:添加、删除O(1) 查询O(n)
双端队列Deque的时间复杂度:插入、删除O(1) 查询O(n)
优先队列Priority Queue 的时间复杂度:插入O(1) 取出O(logN)

【5-070-week 01】学习总结

1. 找重复

任何算法最后都是抽象为「if-else」、「for-loop」、「recursive」代码来表示。所以我们就是要找的逻辑中重复的部分。

2. 刻意练习

这一周最大的收获就是五毒神掌了,刷算法题不应该死磕,算法都是有套路的。比如:「双指针」、「多指针」、「快慢指针」、「哈希表」等等,这些方法需要多写多做就能熟练运用。

有不熟练的类型的题目就针对这个种类反复练习,然后过一天、一周、面试前一周重新做一遍题目,加深记忆。

3. 主动寻求 Feedback

在课上老师给我们介绍了算法题可以去 leetcode 的中文和英文站,看全**和全世界网友的代码和解题**。

在工作、生活中不是时时都有人给你 review 代码,给你提意见。我们也可以在 GitHub 上找优秀的库的源代码、或者看对应编程语言的源代码(如:Java),去学习好代码、工业级代码应该是怎样写的。

4. 优化代码的**

优化算法基本上有两个重要的**:升维、空间换时间。

「升维」的应用:
对链表的查询操作进行优化,进行升维之后就得到了「跳表」这个数据结构。

「空间换时间」的应用:
比如,「两数之和」的哈希表解法。

【580-week 01】第一周学习总结

1、关于这几个数据结构

本周学习了数组、链表、栈和队列等一维数据结构。以及跳表这个二维数据结构。

跳表对我而言是一个未接触过的数据结构。
跳表的优化的**是“升维思维”(或者说是空间换时间)。我们在设计数据库表的时候也会通过冗余字段的方式来提升query的速度,也是用空间换时间。

针对数组的随机访问特性,理解进一步加深,其中解决问题的时候的左右夹逼的方式、将数组当成一个定长的循环链表使用等思路,都是用到了随机访问的特性。

队列的知识点中的双端队列,用来解决滑动窗口问题,让我印象也比较深刻。

2、关于做题方式

对于“五毒神掌”刻意练习的学习方式,坚持的不够好。需要做好规划,持续坚持。

在做题的时候总是会花很多时间去思考,有些题目花的时间很长。自己容易僵持在某几个点上跳不出来,有几道题晚上花了很长时间思考都没有想出来,但是第二天一醒就有了思路。这个学习过程效率比较低,在学习和练习过程中的效率需要想办法提升。

3、收获的学习技巧或者思路

学习一个数据结构的时候,去读一读Java的源代码,是一个非常好的学习方式。能够得到很多思路和学到很多技巧。
数组可以作为很多其他高级数据结构的存储,数组的能力比我之前认识的要强得多。
本周还学到了“左右夹逼,向中间收敛”的思路。其中作业中的接雨水的题目,我的解法就是用的这个思路。
双指针的技巧也是本周学到的思路。双指针或者数组中的双下标,能够解决很多问题。不过对于双指针的熟练使用,我还需要进一步加强。

【606-week01】Java源代码深入理解方式

原本一直角色数据结构跟Java这种高级语言其实相差很远。
通过本周的学习
学习到了如何来看Java方面的源码,并结合数据结构的特性,更能理解Java中数据类型的性能,后续在使用的时候,心里会更清晰,知道该怎么选Java里面的类型,去做相应的业务需求,同时也期待后续的课程让我丰富自己的基础知识,能让自己更好的剖析源码,深入技术的学习。

【420-week 01】算法学习方法

【420-week 01】算法学习方法
第一周学习了四种最基础的数据结构:数组、链表、栈、队列,另外介绍了两种高级数据结构:跳表,优先队列。
数组和链表属于线性结构,具体应用时要根据实际情况来使用。常见的操作有双指针遍历,双向链表的实现。栈适用了具有最近相关性的场景,栈和队列单独使用的较少,一般都是使用双向队列,结合了栈和队列的特点。跳表优化了链表查询,利用空间换时间的**在链表上建立多级索引。优先队列很有用,著名的有LRU。提高算法的中心**即:升维,也叫空间换时间。跳表就是将一维的链表提升为二维,利用多级索引的多个指针,提高查找效率。
知识点相对来说比较简单,重点在于老师提到的学习方法,即“五毒神掌”。
一、对于一道题,先理解题目意思,试着思考题多种解法。如果没有思路,不要跟自己较劲,马上查看前辈们星级较高的解法(LeetCode国内站和国际站),先理解逻辑,对于一些常用的方法要记忆下来;
二、在理解了解法的基础上,不看代码,自己实现。另外还要和其他解法对比,对比时比较时优先关注时间复杂度;
三、一天后,再次解题。对于不熟练的题目和解法,再次训练,走出舒适区;
四、一周后,再次解题。对于不熟练的题目和解法,进行专项训练;
五、这点主要针对面试,在面试前重新刷之前做过的题目,进行恢复性训练。
人都是有懒惰性的,术语叫做熵增,一个房子如果长时间不打扫,总会是灰尘越来越多。为了克服熵增,我们要自律,就像房子要定期打扫一样,算法要多次练习,达到熟能生巧,遵从“一万小时法则”。一道题目不能满足于一种解法,其他优秀的解法我们也要学习;算法也不能满足于某种类型,更难的算法我们要迎难而上,走出自己的“舒适区”,自己才能提高的更快。

【032-Week1】学习总结

通过这第一周的学习感受到了过遍数这种方法太有效了!大大缓解了我一看就会,遇题就蒙的毛病。数组、链表各自的定义、特点这些理论知识不难,大学也接触过,但是一遇到具体的问题就不会了。这次一遍一遍的刷题过程中又加强了这块理论知识的理解,以后再遇到链表相关的题目也知道大概用什么方法去尝试了。

【428-week1】关于栈的一些新的理解

关于栈的一些新的理解

  • 栈的定义:栈(stack)又名堆栈,它是一种运算受限的线性表。其限制是仅允许在表的一端进行插入和删除运算。这一端被称为栈顶,相对地,把另一端称为栈底。向一个栈插入新元素又称为进栈、入栈或压栈,它是把新元素放到栈顶元素的上面,使之成为新的栈顶元素;从一个栈删除元素又称之为出栈或退栈,它是把栈顶元素删除掉,使其邻居的元素成之为新的栈顶元素。

  • 栈的特点:先入后出。符合这个特征的数据才可以在栈中存储。

  • 在计算机系统中,栈则是一个具有以上属性的动态内存区域。程序可以将数据压入栈中,也可以将数据从栈顶弹出。

  • 栈在程序的运行中有举足轻重的作用,最重要的是栈保存了一个函数调用时所需要的维护信息,这常常称之为堆栈帧或者活动记录。堆栈帧一般包含如下几方面的信息:

    1. 函数的返回地址和参数。
    2. 临时变量:包括函数的非静态局部变量以及编译器自动生成的其他临时变量

栈的作用原理

  • 一个函数设计里面,有2个问题:

    1. 参数传递

      • 传递参数的目的,是为了代码可以重用,让一种方法可以应用到更多的场合,而不需要为N种情况写N套类似的代码。
      • 那用什么方法来做参数的传递?可以选择:
      • 为了速度快,使用cpu的寄存器传递参数。这会碰到一个问题,cpu寄存器的数量是有限的,当函数内再想调用子函数的时候,再使用原有的cpu寄存器就会冲突了。想利用寄存器传参,就必须在调用子函数前把寄存器存储起来,然后当函数退出的时候再恢复。
      • 利用某些ram(随机存取存储器)的区域来传递参数。这和上面a的情况几乎一样,当函数嵌套调用的时候,还是会出现冲突,依然面临要把原本数据保存到其他地方,再调用嵌套函数。并且保存到什么地方,也面临困难,无论临时存储到哪里,都会有上面传递参数一样的困境。
    2. 函数里面也有可能要使用到局部变量,而不能总是用全局变量。则局部变量存储到哪里合适,即不能让函数嵌套的时候有冲突,又要注重效率。

      • 以上问题的解决办法,都可以利用栈的结构体来解决:
        1. 寄存器传参的冲突,可以把寄存器的值临时压入栈里面,非寄存器传参也可以压入到栈里面。
        2. 局部变量的使用也可以利用栈里面的内存空间,只需要移动下栈指针,腾出局部变量占用的空间。最后利用栈指针的偏移来完成存取。于是函数的这些参数和变量的存储演变成记住一个栈指针的地址,每次函数被调用的时候,都配套一个栈指针地址,即使循环嵌套调用函数,只要对应函数栈指针是不同的,也不会出现冲突。
        3. 利用栈,当函数不断调用的时候,不断的有参数局部变量入栈,栈里面会形成一个函数栈帧的结构,一个栈帧结构归属于一次函数的调用。栈的空间也是有限的,如果不限制的使用,就会出现典型的栈溢出的问题。有了栈帧的框架在,我们在分析问题的时候,如果能获取到当时的栈的内容,则有机会调查当时可能出现的问题。
  • 然而栈存在的意义还不止这点,有了它的存在,才能构建出操作系统的多任务模式。

总结

  • 栈的作用分为以下几点:
    1. 栈是每个函数架构的基础,实现了函数的重复利用。
    2. 问题发生的时候,可以利用栈来了解问题发生的情况。
    3. 栈是构建出操作系统多任务模式的基础。

408 week1学习总结

本周学习最大心得是了解了一些之前不熟悉的数据结构,例如跳表,优先队列。老师所讲的刷题法对我启发很大,从前总想着即使想不出来也要不看答案自己解决因而浪费了很多时间,老师提到的五遍刷题法对于不熟悉或者没有思路的题目非常有效,而且在学习过程中还可以集思广益,学习大家的优秀的解题方法。老师带着解题的视频和课后有关的扩展资料也非常有帮助。

【400-week1】学习总结

数据结构与算法结合才有意义,设计出算法需要找到合适的数据结构去高效地实现算法。

以239. 滑动窗口最大值为例,每次移动窗口,都有元素入队、出队,所以需要用到队列数据结构,但是为了能优化最大值的选取,就需要在队列的基础上加入排序的因素,于是就有了单调队列这个数据结构,每次更新队列都要用新加入的最大值清理一遍队列元素,程序效率得到提高。

以84. 柱状图中最大的矩形为例,为了能高效地扫描柱高,选用栈这个数据结构,同时要精心选择压栈与出栈的时机条件,才能高效地找出目标矩形面积。

【022-week 01】数组、链表、队列相关总结

学习笔记
一、数组
1.数组:在计算机存储中是一段连续的地址,每个地址都可以通过内存管理器直接访问,数组的索引表达的是offset的语意,对任何一个元素,都可以使用y = x + b(y是元素地址,x是偏移量,b是数组首元素地址)计算得到任意元素的地址,所以数组访问任意位置元素的时间是一样的。引用@mo-xun
优点:随机访问的时候时间复杂度O(1)
缺点:插入、删除元素的时候时间复杂度O(n)

2.相对于JDK中是 ArrayList 的结构,在 add 的时候会判断容量是否足够,不够的话会会扩容2倍 ensureCapacity,期间扩容和后移/前移操作都是System.arraycopy 来拷贝

3.数组基本操作时间复杂度
prepend O(1)
append O(1)
lookup O(1)
insert O(n)
delete O(n)

二、链表
1.链表:由一个一个节点连接一起,相比于数组对于频繁插入、删除的时候我们会使用链表
优点:插入、删除时间复杂度都O(1)
缺点:顺序访问的时间复杂度O(n)
Node包含value/next/previous是双向链表,头指针用Head表示、尾指针用Tail表示,最后一个next指向null

2.相对于JKD中是 LinkedList 的结构,它的结构是双向链表,在Entry中有一个Entry next和Entry previous,在外层成员变量维护这first和last头尾指针和size这个链表的大小

3.链表基本操作时间复杂度
prepend O(1)
append O(1)
lookup O(n)
insert O(1)
delete O(1)

三、跳表
1.跳表:在Redis中有应用,跳表是为了优化链表的随机访问的缺陷而产生的

2.如何给链表加速?
方法一:添加头尾指针,这样在查询头尾节点的时候O(1)时间就可以拿出
方法二:中心**就是升维,空间来换取时间,基于方法一就可以扩展了,我多添加一些指针

3.通过给链表加速,我们不断给中间插入指针,中间的中间.....持续下去(所以每层索引遍历的节点个数是3),那么第一级索引就建立出来了,原始链表速度是1,一级索引速度就是2,然后同理建立二级索引相对于原始链表跨4个元素,速度是4,以此类推增加多级索引

4.一共有n个元素,需要增加log2^n-1个级索引证明,跳表查询时间时间复杂度等于层数所以为log2^n
证明推理:链表有n个第一级索引是n/2个元素,第二级是n/4,第h级是n/2^h
假设索引有h级,最高的索引有2个节点则有 n/2^h = 2 退出 h=log2^n-1,同理假设最高层索引有一个则需要建立 log2^n层索引

5.跳表空间复杂度
原始链表大小为n,每2个结点抽1个,每层索引的结点数: n/2,n/4,n/8...4,2
原始链表大小为n,每3个结点抽1个,每层索引的结点数: n/3,n/9,n/27...4,2
空间复杂度为O(n) 数量级是n 收敛起来还是n

四、缓存
1.缓存:这里说的缓存是一种广义的概念,在计算机存储层次结构中,低一层的存储器都可以看做是高一层的缓存。缓存之所以有效是因为程序和数据的局部性(locality),程序会按固定的顺序执行,数据会存放在连续的内存空间并反复读写。

2.LRU-Cache最近最少使用(LRU,Least Recently Used)
简书:LRU实现 hashmap+双向链表 https://www.jianshu.com/p/b1ab4a170c3c

3.为什么Redis用跳表而不用红黑树
并发场景下红黑树要锁多个节点比较复杂
排序集合通常使用zrange和zrevrange
便于实现、调试

dubbo LinkedList 实现LRU-Cache

五、栈
Stack:先入后出;添加、删除都是O(1);查询是O(n)
基本方法:
boolean empty():判断这个栈是否为空
E peek():查看栈顶元素
E pop():删除栈顶元素
E push(E item) :从栈顶入栈
int search(Object o):查询一个元素在stack的下标

六、队列
Queue:先入先出;添加、删除都是O(1),在Java中是接口下面的子类有很多如:LinkedList、LinkedBlockingQueue、DelayQueue、PriorityQueue等
基本方法:
插入 抛异常的add(e)/返回特殊值的 offer(e)
删除 抛异常的remove()/返回特殊值的poll()
访问元素 抛异常的element()/返回特殊值peek()

七、双端队列
Deque(Double-ended Queue):双端队列,可以从前后添加和删除元素;添加、删除都是O(1) 查询O(n),在Java中实现有ArrayDeque,ConcurrentLinkedDeque,LinkedBlockingDeque,LinkedList
基本方法:
从头部操作 从尾部操作
抛异常 特殊值 抛异常 特殊值
插入 addFirst(e) offerFirst(e) addLast(e) offerLast(e)
删除 removeFirst() pollFirst() removeLast() pollLast()
访问元素 getFirst() peekFirst() getLast() peekLast()

八、优先队列
PriorityQueue 插入操作O(1)、去除操作O(logn)按照元素的优先级取出,保证了一定的有序性,底层实现可以是heap、bst、treap,必须要实现comparator方法就是比较大小用于保证有序
基本方法:
boolean add(E e):添加元素
void clear():清空优先队列
boolean offer():添加元素
boolean remove(Object o) :删除元素
poll/peek

九、对于Queue和PriorityQueue分析
对于Queue来说很简单它只是一个接口,主要有add添加抛异常、remove移除头元素、element返回头元素、offer添加返回特殊值、poll移除头元素、peek返回头元素,前面的会抛出异常而后面的几个会返回特殊值
Queue主要的实现类有ArrayBlockingQueue、ArrayDeque、ConcurrentLinekedQueue、ConcurrentLinekedDeque、DelayQueue、LinkedList、LinkedBlockingQueue、LinkedBlockingDeque、PriorityQueue等。

ArrayBlockingQueue举例核心成员变量有:

  • 元素数组Object[] items
  • 放入队头元素的下标 takeIndex
  • 拿走队尾元素的下标 putIndex
  • 队列元素数量 count

对于并发和锁的方面主要有:

  • ReentrantLock 可重入锁 具有对中断有响应、可限时、可公平锁的特点
  • 2个Condition 用于控制放入和拿走元素的条件 实现线程间的协调

对于PriorityQueue他是属于Queue的一种实现,底层结构使用数组,初始化大小为11个
在初始化的时候首先会heapify构建这个堆,在插入的时候会siftUp调整这个堆以保证每次拿出来
对顶元素都是最小值,在出队列的时候会shiftDown然后将最后一个元素放到0位置整体在向下进行调整使得再次成为堆

十、改写Deque

    Deque<String> deque = new LinkedList<>();

    deque.addFirst("a");
    deque.addFirst("b");
    deque.addLast("c");
    System.out.println(deque);
    String peek = deque.peek();
    System.out.println(peek);
    System.out.println(deque);
    while (deque.size() > 0) {
        System.out.println(deque.pop());
    }
    System.out.println(deque);

[390-Week01] 学习总结(1.学习须知 2.做题)

第一周的学习收获满满,老师讲的很有意思,举例也很生动,题目多练,有点上头哈哈~

主要分为两大块,记录个人感觉有启发性的内容(不完全):

一、学习须知
(1)好的编码习惯,自顶向下编程,高效使用IDE快捷键(光标一个一个挪确实有点矬)
(2)如何获取有效信息

  • google关键字搜索(最好用英文),熟悉英文术语
    
  • 查看官方文档及源码(比如 Java,第一次觉得Oracle的文档这么可爱,不要害怕英文,还有词典可用)
    

二、做题
(1)刷题五遍法(不赘述,至少5遍 实际不止)

  •  仔细审题,比较多种解法取、复杂度分析,取最优解,注意执行时间;
    
  •  中文站做完题看题解,国际站Most Votes语言相关的前几个(一般前三个即可);
    

最大的误区:做题只做一遍!

(2)算法
核心:
1.升维 2.以空间换时间

复杂的算法演化,最终分为三种: if else, for loop, recursion递归    找最近的重复子问题

(3)“固定”的套路:

  •   “左右夹逼”,获取左右边界,往中间慢慢收敛(题目:11.盛水最多的容器 84.柱状图的最大矩形)
    
  •   “快慢指针”(题目:141.环形链表 举例-赛跑 快的人与慢的人最终相遇)
    
  •   “寻找相关性“ 栈(题目:20.有效的括号 举例-洋葱)
    

说明:
1.老师教会我们方法技巧,多练多琢磨,融会贯通。
2.额外做笔记,有助于概念理解以及算法剖析涂涂画画,也有利于后面面试复习。
3.详细的知识点可参考王争老师的《算法与数据结构之美》专栏。

【416-week 01】第一周学习总结

一、本周要点总结
1.自顶向下的编程方式
之前写代码的习惯不大好,没有用层次化、结构化的方式区分主干逻辑和分支逻辑,经常让大脑陷入到极大的认知负荷中。
覃超老师的自顶向下的编程方式则将问题拆分,列出大纲,让大脑一次只集中处理一个问题点,有效地减少了认知负荷,让思路更有条理性。
这其实和写文章是一样的道理。

2.学会了双指针的使用
(1)两层循环的使用:例如将数组中两两元素求和时,外层指针从0到数组长度减2,内层指针从1到数组长度减1,这样错开后,正好可以将所有的情况都遍历
(2)左右指针往中间收敛:可以用于找满足条件的值,比如最小值,最大值,等于某个特定值的组合
(3)快慢指针的使用:快指针和慢指针的区别在于,快指针的步长大于慢指针。两者结合可用于判断链表是否有环,也可以用于特定场景下的元素值的交换

3.意识到了循环、条件语句、递归的重要性
在这一周的练习中发现很多问题其实都用到了循环语句、条件语句,有些题目的暴力解法用到了递归。
正如覃超老师所说,计算机最终其实就是处理重复性的语句,所以编程可以说是将复杂代码拆分成循环、条件、递归等语句的过程。我认为找到最近重复特性其实是计算机世界的一种通用的底层的规律。找到了规律在规律上努力便可以事半功倍。

二、存在的不足
1.投入学习算法的时间偏少
第一周是自己的一个尝试周,因为此前并没有大量地算法学习,基础较为薄弱。这也导致了自己不能按照别人投入学习的时间作为参考标准。
经过一周的观察和回顾,发现对于自己而言每天2小时的算法学习时间是不够的。

2.五毒神掌的践行力度不够
一方面是由于算法投入的时间不够,另一方面是心态方面,总是想着把每道题都快速做一遍,结果是题做了,但练习的次数不够,做了也就忘了。
自己的算法基础薄弱,那就先将课程中提到的一些题目,以及课后的作业中部分简单题目作为主要练习对象。每次用五毒神掌先练好那几道题,熟练之后推进剩余部分。

三、接下来的调整
1.增加算法学习的时间,删减每日不重要的事务
2.增加五毒神掌的进行力度,拆分练习题,并分阶段完成练习

【024-week 01】删除排序数组中的重复项-总结

  • 前两个月刷过一段时间leetcode,所以看到这道题时第一印象是用双指针法解决。但是实际上手花了接近20分钟时间,还是未能写出正确的双指针解决方案,于是直接看题解。里面关于复制数组项及跳过项时感觉有点绕,属于看题解觉得明白了,实际上手就不懂的情况。
  • 当第二次着手写时,return i 后依然错误,再次看题解,答案很简单,关于return i + 1也是脑回路绕了半天才想通。
  • 总之是自己基本功不够,看来每次老师布置的课后习题都需要去认真做。

【5-006-week 01】第一周学习总结

内容总结
本周主要学习了基本的数据结构,譬如数组,链表,栈以及队列等等,以及这些数据结构的一些操作。首先对于常见数据结构的时间和空间复杂度,都进行了理清和熟悉,尤其是对于数组和链表的插入删除,以及查询的复杂度有了新的认知。
此外,对于跳表,之前在其他方面的学习中接触很少,明白了以空间换时间的思路,针对链表查询慢的缺点从而设计的跳表,其核心**就是通过索引的方法进行“加速”,从而使时间复杂度降到O(logN)级别,尽管在空间复杂度上有所提升,但是在工程上确实能够有助于高性能程序的优化,毕竟现在存储价格不再像以前那么昂贵。栈和队列在大学学习阶段只是有一个FIFO这种粗浅的概念,而具体的使用在之后的工程中遇到的不多,这次通过学习还了解到了双端队列的概念,并对这些数据结构常见的操作的复杂度,以及应用有了一定的认识。
学习心得
“五毒神掌”+听课的结合,是本周最大的收获之一,有些内容可能初听感觉还是有不明白的地方,但是听完课然后自己亲自动手写一遍并且背诵理解之后,在进行反复的训练之后,就逐渐能够理解一些算法中原本不理解的地方,这是本次的学习中所获得进步。另外,通过自己的学习情况,我这边在第二遍以及第三遍刷题的时候,结合了之前同学的学习建议,使用iPad+Onenote的方式,将已经刷过的题目再刷题之后在进行默写一次并进行整理总结,目前看来效果还不错,希望到四刷以及面试前的五刷的时候,能够有进一步强化的效果。

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.