数组是一维的线性数据结构。数组在内存中占用一段连续的空间,访问一个具体位置的元素时,通过数组的首地址加上偏移量可以在O(1)的时间里找到这个元素。同样由于数组要求空间上的连续,所以数组在删除或者添加一个元素时,或多或少都需要移动一些元素。比如一个长度为n的数组:
在第i个位置添加一个元素,需要将i+1到n-1位置的元素向后移动一个位置。
删除第i个元素时,需要将i+1到n-1位置的元素,向前移动一个位置
这两项操作的平均复杂度都是O(N)
链表与数组一样,都是一维的线性数据结构,每个节点都维护了一个指向后驱的指针next。在工程领域,比如java中的链表,实际上是一个双向的指针,也就是除了一个后驱的next,还有一个前驱的prev。
链表的添加和删除元素的时间复杂度是O(1)
// 在target后添加一个节点
ListNode node = new ListNode(value)
node.next = target.next
target.next = node
// 删除target元素
if(prev.next == target) {
prev.next = target.next;
target == null;
}
链表在内存中存储不连续,所以没有办法通过地址偏移的方式快速找到目标元素,链表访问的时间复杂度是O(N)
栈和队列是对线性一维数据结构加以不同约束的数据结构,二者都可以通过双向链表或者数组来实现。其中
栈: 后进先出
队列: 先进先出
五毒神掌护我进步。最重要的一点就是过遍数。从我实际学习算法的路径来说,虽说也算是信息领域相关专业出身,从事的也是软件行业,但是毕竟CS的专业课比如数据结构之类的没有系统的学习过。工作后意识到这些基本功的重要性,也零零总总的看了不少书,LeetCode更是早早就注册了。然而似乎不得其法,当下好像看明白的知识,或者是实操过的题目,用不了一天,就忘光光。结合训练营的开展,我意识到一个问题,我在毕业之后的学习方法,怎么就和初中时期一样?二者的区别在于,简单的逻辑以及少量的概念,确实可以不怎么通过刻意训练的方式记住。但是知识本身存在客观的难度,要熟练掌握这些内容,必须要下苦工。这番苦工并不是对我智力的否定,而是掌握这些知识,必须要通过反复训练,算法思维和肌肉记忆一样,必须刻意。
快慢指针探测
两端逼近
有时候引入额外的空间除了会降低算法的时间复杂度,一定程度上其实也解放了思维的复杂度
一个比较大的问题,在局部上具有相同的特征和操作,比如链表的两两交换
撇开算法本身是计算机工程领域的基本功之外。我个人还有一些比较功利的认知。我认为,算法是普通人锻炼复杂问题思考能力的最具性价比的方式了。许多高端岗位,无论是业务岗,管理岗或是技术岗,基础岗位需要的技能总能通过时间来到达瓶颈,无他,唯手熟尔。但如果需要踏上更高的岗位,除了天时地利,工程师自己也必须掌握复杂问题的思考能力,比如涉及到架构层面,往往需要一些复杂的思考,就算有了知识面,但是没有过系统化的思维训练也是无法满足复杂架构的设计要求的。