1.力扣青蛙跳问题
主要考察的是字符串能否按顺序组成多个 CROAK。如果某一个 O 前边没有 R,那就失败。如果它总共的字符个数不是 5 的倍数,那就失败。如果最后发现有没有完整的字符串,比如说只有 CRO,或者只有 CROA,那它也失败。
具体的思路就是通过五个数组分别计算处于 CROAK 每个字符串每个字符的个数。如果处于比如说 O 的状态,但是当前没有处于 R 的状态的,那就说明失败。
2.最长回文子串,力扣第 5 题。
这个题可以用动态规划解决,也可以用暴力枚举去解决。暴力枚举的解决方法的思路就是,对于每一个位置,把它当成中间位置,可以判断最长的奇数的字符串的长度,和把它当成偶数位置的左边那个中间的位置,最长的偶数长度的回文串的长度。
然后官方的解法是使用动态规划。动态规划的过程中,i 是从 N 减一到 0,然后 j 是从 i 到 N 减一。
八股
然后是自己一些八股的逐字稿的复盘。
1.为什么 MySQL 的索引使用 B 加树而不使用红黑树?
这个的话,之前理解的比较浅,也不是说比较浅,之前理解的都是,比如说为什么不使用哈希表?因为哈希表它不支持范围查找,不支持顺序查找。为什么不使用 B 树?因为 B 树磁盘 IO 多,而且它的范围查找也是需要在树中去便利的,它没有去使用很方法很便利的方法去顺序查找。而红黑树呢,本质上是二路平衡搜索树,而 B 加树是多路平衡搜索树。首先,红黑树的层次二路的话,一定是比多路是高的,所以说磁盘 IO 多。除此之外,因为它不像 B 加树在叶子节点用双链表链接起来,所以说它的范围查找和顺序查找的支持不如 B 加树。
2.为什么 B 加树的叶子节点使用双链表链接起来?非叶子节点是否需要链接呢?
这部分我之前一直以为它的叶子节点是单向链表链接的,但是我没有想到它可以逆向的范围去查询。而且双向的话确实更方便,就好像设计 LRU 的时候,最好就是设计双向链表,这样的话就很方便去尾部去剔除。
正式回答,使用双向链表的话,因为 B 加树的数据都存储在叶子节点,它是按照 K 有序存储的。使用双向链表便于范围查找,便于按照顺序或者逆序去查找。而非叶子节点存储的只有索引和指向子节点的指针,用于索引叶子节点。所以说是不不需要有横向查找这个需求的,所以说它的非叶子节点不需要使用双向链表。
3.事务的四个特性分别是什么?分别是怎么实现的?
其实这个问题,这些词之前都学过,但是还是了解的不是比较系统,但是也是主要是作为一个记忆去背吧。
事务的四个特性分别是 ACID,也就是原子性、一致性、隔离性和持久性。其中一致性是最终目的,事务主要就是通过原子性、隔离性和持久性去实现一致性。
原子性是通过 Undo log 去实现的,Undo log 记录旧值或者反向操作。而隔离性是通过多版本并发控制和临界锁去实现的,多版本并发控制保证了快照读的隔离性,而当前读的隔离性需要使用临界锁。持久性通过 Redo log,Redo log 是预写机制,是预写日志。
一致性是通过 AID 以及数据库的约束和业务逻辑层去共同实现的。
4.死锁产生的原因以及解决方法。
死锁产生的条件有四个,分别是互斥、请求和保持、不剥夺、循环等待。第一种解决方法是死锁预防,就是破坏这四个条件之一。可以一次按照顺序去申请资源,或者是一次必须申请所有资源才去申请,或者是破坏不剥夺条件。然后可以采用死锁避免,比如说银行家。算法去判断是否可能发生死锁,决定是否分配资源。也可以使用检测与恢复,就是检测到死锁之后去杀死进程、释放资源或者是回滚事务。还有就是采用鸵鸟策略,对死锁现象忽视。
5.静态库和动态库的区别。
静态库和动态库的区别主要是在链接时机和共享方式上。
静态库它的链接发生在编译时期,库代码被复制到可执行文件中,多个程序可能会重复包含静态库的代码。然后静态库更新的话需要进行重新编译,它的文件通常更大。
动态库它的编译期间只是记录依赖关系,在运行时才加载动态库代码。它的优点是多个文件可以共享动态库代码,缺点是可能出现动态库缺失、版本不兼容的问题。
主要是 MySQL 的索引的实现,这部分好像是一个常考点。除此之外,还有就是事务的四个特性,还有它的隔离级别,这是在实现层面的常考点。在操作层面的常考点主要就是 SQL 语句怎么写,还有就是怎么去解决慢查询问题,怎么去优化。
然后在编译这边,静态库动态库是一个,然后编译的阶段是一个,C++ 的内存模型是一个。还有关于多态怎么去实现,多态的类型这边是一个。还有就是关于智能指针,还有内存分配这些。