前言:最近积累了一些算法题量,正在刷东神的算法笔记,监督自己+记录下读后启发,顺便帮助道友们阅读
这一部分老生常谈,数据的存储方式只有顺序存储和链式存储。
最基本的数组和链表对应这两者,栈和队列都可以用顺序存储和链式存储实现;图的两种表示方法,邻接表就是链表,邻接矩阵就是二维数组;散列表就是通过散列函数把键映射到一个大数组里;树用数组实现就是堆,因为堆是一个完全二叉树,用数组存储不需要节点指针,操作也比较简单,用链表实现就是常见的树。
在性能上,数组由于是紧凑连续存储,可以随机访问,通过索引快速找到对应元素,而且相对节约存储空间。链表因为元素不连续,而是靠指针指向下一个元素的位置,所以不存在数组的扩容问题;如果知道某一元素的前驱和后驱,操作指针即可删除该元素或者插入新元素,时间复杂度 O(1)。但是正因为存储空间不连续,你无法根据一个索引算出对应元素的地址,所以不能随机访问;而且由于每个元素必须存储指向前后元素位置的指针,会消耗相对更多的储存空间。
众所周知的增删查改,抽象后就是遍历和访问。而遍历和访问分为线性的和非线性,线性是 for/while 迭代为代表,非线性是递归为代表。
看了下作者的观点,发现自己真的对算法有误解,刷算法题重点是计算机思维,需要你能够站在计算机的视角,抽象、化简实际问题,然后用合理的数据结构去解决问题,而不是数学建模和调参经验。针对计算机的特点,算法题就是在穷举+优化。
算法的技巧上,都是被题目狠狠教做人
数组的有二分,双指针,滑动窗口,前缀和差分
链表日常双指针或者多指针,偶尔用哨兵节点
二叉树分为遍历一遍和利用递归分解,分别对应回溯和动态规划,有的时候需要剪枝和备忘录