首先说明,答主24年毕业,现在开始刷题准备面试。计算机专业,学过数据结构、系统和网络,但是都是半吊子,做题就不会的那种,常用语言是python,为了方便数据结构也会用c刷。打算在这里记录一下我的学习笔记,方便自己以后复习,也方便和我一样的人参考。(纯小白就算了,好歹有点计算机基础打底)目前阶段是学习labuladong公众号的笔记,我仅按照自己的学习步骤记录我的想法。所有内容的出处我都会说明白是从哪里看的。
一、数据结构的存储方式
数据结构只有两种存储方式:数组和链表
数组的实现需要考虑扩容和缩容,内存不一定能分配出你想要的大小,但是每个节点占用的空间小,只需要存储相应的元素。链表需要多加一块内存来存储节点指针,但是不用考虑扩容和缩容。
一些“高级”数据结构:
图:两种表示方法:用二维数组表示就是邻接矩阵、用链表表述就是邻接表。邻接矩阵可以快速判断连通性,但是对于稀疏的图很耗费空间。邻接表不那么耗费空间,但是很多操作不如矩阵计算方便。
树:用数组实现就是堆,堆是一个完全二叉树,操作简单。但是很多树不是完全二叉树,就需要链表实现,有很多种类的树来解决不同的问题,例如B+树、二叉搜索树等。
散列表(哈希表):是根据关键码值而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。在处理散列冲突的时候,用到链地址法(拉链法)需要额外的空间存储指针、线性探查法需要数组特性,以便连续寻址。
存储方式的优缺点:
数组:连续存储,可以随机访问,通过索引快速找到对应元素,而且相对节约存储空间。一旦扩容,需要重新分配一块更大的空间,再把数据全部复制过去,时间复杂度 O(N),需要考虑扩容和缩容。插入和删除数据每次都要动后面所有的数据,时间复杂度 O(N),不方便插入和删除操作。
链表:靠指针指向下一个元素的位置,不存在数组的扩容问题;当知道某一元素的前驱和后驱,操作指针即可删除该元素或者插入新元素,时间复杂度 O(1),方便插入和删除。不能随机访问,由于每个元素必须存储指向前后元素位置的指针,所以每个节点的存储空间更大。
二、数据结构的基本操作
所有数据结构都是为了应对不同场景中高效的遍历、访问、增删改查。
各种数据结构的遍历 + 访问无非两种形式:线性的和非线性的。线性就是 for/while 迭代为代表,非线性就是递归为代表。
数组遍历框架,典型的线性迭代结构:
void traverse(int [] arr){
for(int i =0 ; i < arr.length; i++){}
}
链表遍历框架,兼具迭代和递归结构:
class ListNode{
int val;
ListNode next;}
void traverse( ListNode head){
for (ListNode p = head; p!=null; p=p.next){
}// 迭代访问
}
void traverse( ListNode head){
traverse(head.next)// 递归访问 head.val
}
二叉树遍历的递归结构:
class TreeNode{
int val;
TreeNode left, right;
}
void traverse(TreeNode root){
traverse(root.left)
traverse(root.right)
}
说实话,虽然递归用起来简单,但是我之前学数据结构以及考研的时候,都不考递归。。。不知道面试题是什么套路,评论区可以讨论一下。
三、算法
数据结构是工具,算法是通过合适的工具解决特定问题的方法。
我看的公众号建议先刷树的题目,学会从算法中抽取框架,因为说白了,就是看一下解决问题是什么工具,而这些工具的操作基本离不开遍历、搜索、增删改查,从源头找问题的解决方法。
以下内容是公众号的表述,我现阶段是选择记录这个思路:算法的本质就是「穷举」、看到一道算法题,可以从这两个维度去思考:1、如何穷举?2、如何聪明地穷举?
递归类问题,最典型的动态规划系列问题,难点就是如何穷举,找不到递归方程就没法进行,本质上有点找数学方程的意思,归纳不出方程,就没法递归。
如何聪明的穷举,比如一些非递归算法技巧,这些技巧比如KMP、贪心算法,靠自己比较难想出来,得学过才会用。
四、刷题准备
目前打算从链表开始刷,学习一段时间链表后,再去力扣刷几十道题看看自己水准。我会每天把自己的学习内容和刷题内容以及对算法自己的想法写到这个系列,就是纯笔记。
1974

被折叠的 条评论
为什么被折叠?



