大家好,我是白露呀。
今天我在牛客上看到一篇帖子,一位网友说自己收到一个 offer ,薪资很高:60k*13,大约一年有近80万。
但是有个要求是外包到新疆的乌鲁木齐,他拿不定主意,就在牛客上发了这个帖子。
然后这个“凡尔赛式”的发言就把网友们给搞懵了,纷纷留下了他们的“祝福”,有网友说**“外派月球都可以”**。
还有网友说“别说新疆,让我去西伯利亚喂狼都行”、“**6万,把我派到国外我都愿意”。
总而言之,大伙对这位网友的遭遇都表示强烈的羡慕。
在我看来,如果是刚毕业的同学,或者急需用钱的同学,并且对地域并没有强烈要求的话,这个岗位完全可以接受。
毕竟乌鲁木齐是新疆的省会城市,完全可以挣几年钱再考虑一直定居还是跳槽去其他的城市。
白露我一直没有去过新疆,但是家里有亲戚在新疆做过几年生意,听他们说新疆其实挺舒服的,景色优美,就是一开始去高反有点受不了。
今天我给大家带来一篇面经,正好是乌鲁木齐一个小厂的面试,总的来说,大部分考查的八股文知识,各位同学可以收藏、阅读、练习、划线!春招再冲刺一波!
面经开始
面试官: 首先,告诉我你学过哪些数据结构?
求职者: 我学过的数据结构包括数组、链表、栈、队列、哈希表、二叉树、图、堆和红黑树等。这些数据结构是计算机科学中的基础,它们在解决各种算法问题中都有广泛应用。
面试官: 很好。那你能解决N皇后问题吗?
求职者: 是的,N皇后问题是一个经典的回溯算法问题,其目标是将N个皇后放置在N*N的棋盘上,使得它们彼此不能相互攻击。我会使用一个递归函数来尝试每一行的每一个位置,通过检查列和对角线上是否已经有皇后来保证不会相互攻击。
面试官: 你学过哪些数据库?
求职者: 我学过关系型数据库如MySQL和PostgreSQL,了解它们的基本操作和一些优化技巧。我也熟悉非关系型数据库,比如MongoDB和Redis,理解它们的数据模型和适用场景。
面试官: 谈谈事务的四大特性。
求职者: 事务的四大特性是原子性、一致性、隔离性和持久性。原子性保证事务中的操作要么全部成功,要么全部失败;一致性确保事务执行后数据库从一个合法状态转移到另一个合法状态;隔离性保证并发事务之间不会互相影响;持久性则是指事务一旦提交,其结果就会永久保存。
面试官: 那么,如何保证事务的四大特性?
求职者: 数据库管理系统通常通过锁机制、日志记录和隔离级别来保证事务的ACID特性。比如,通过锁来实现隔离性,通过写入undo log和redo log来实现原子性和持久性。
面试官: 你了解索引的底层实现吗?
求职者: 是的,大多数数据库的索引是使用B+树实现的。B+树是一种平衡多路查找树,它可以保持数据排序,而且由于其广泛的分支,可以减少磁盘I/O操作,提高查询效率。
面试官: 如果查询一个表中的数据很慢,可能是什么原因?你会怎么解决?
求职者: 查询慢可能是由于缺乏有效的索引、数据量过大、磁盘I/O瓶颈或查询语句不够优化等原因造成的。我会先检查执行计划,检查是否有合适的索引,然后考虑是否需要优化查询语句或调整数据库的配置。
面试官: 你在Redis中用过哪些数据结构?怎么用的?
求职者: 在Redis中我使用过字符串、哈希、列表、集合和有序集合。比如,我会使用列表来实现队列,用集合来处理去重,使用有序集合来做范围查询和排行榜等功能。
面试官: 你了解Redis的持久化吗?
求职者: 是的,Redis提供了RDB和AOF两种持久化机制。RDB会在指定的时间间隔内生成数据快照,而AOF则记录每次写操作,可以提供更好的持久性保证。
面试官: 在你的项目中,你是如何解决数据一致性问题的?你提到了两种方案,最终使用了哪一种?
求职者: 在我的项目中,最初我们使用了删除缓存和修改数据库的方式来保证一致性,但后来我们发现使用延迟队列加上双删的方案更加有效,因此我们最终采用了后者。
面试官: 如果Redis满了会发生什么?
求职者: 如果Redis满了,它将根据配置的淘汰策略来移除一些键,比如LRU(最近最少使用)策略。如果没有合适的淘汰策略,Redis可能会拒绝写操作。
面试官: 你有实现过LRU或LFU吗?
求职者: 是的,我实现过LRU,它可以通过结合HashMap和双向链表来实现。我还了解LFU的概念,它通常需要两个HashMap加上链表来跟踪使用频率。
**LFU(Least Frequently Used,最不经常使用)和LRU(Least Recently Used,最近最少使用)**都是缓存淘汰算法。
- LFU根据数据被访问的次数来决定淘汰哪些数据。具体来说,它会淘汰访问次数最少的数据。如果存在多个访问次数相同的数据,可能会根据具体实现来选择淘汰哪一个。LFU的核心在于维护一个按访问频率排序的数据结构,以便快速找到访问次数最少的数据。
- LRU则是根据数据的访问时间来决定淘汰哪些数据。最近最少使用的数据(即最长时间没有被访问的数据)首先被淘汰。LRU通常使用一个链表来实现,链表的头部是最近访问的数据,尾部是最久未访问的数据。
实现LRU缓存,一种简单的方法是使用LinkedHashMap,因为LinkedHashMap内部已经实现了按访问顺序的排序功能。:
import java.util.LinkedHashMap;
import java.util.Map;public class LRUCache<K, V> extends LinkedHashMap<K, V> {private final int capacity;public LRUCache(int capacity) {// 设置accessOrder为true,使LinkedHashMap按访问顺序排序super(capacity, 0.75f, true);this.capacity = capacity;}@Overrideprotected boolean removeEldestEntry(Map.Entry<K, V> eldest) {// 当缓存项数量超过容量时,移除最老的数据return size() > capacity;}public static void main(String[] args) {LRUCache<Integer, String> cache = new LRUCache<>(3);cache.put(1, "a");cache.put(2, "b");cache.put(3, "c");System.out.println(cache.keySet()); // [1, 2, 3]cache.get(1); // 访问数据1cache.put(4, "d"); // 添加数据4,导致数据2被淘汰System.out.println(cache.keySet()); // [3, 1, 4]}
}
这个LRUCache类继承自LinkedHashMap,并重写了removeEldestEntry
方法。这个方法会在每次添加新元素后调用,如果返回true,则会移除最老的元素(此处的"最老"是指最久未被访问的元素)。通过调整accessOrder参数,我们使LinkedHashMap按访问顺序而非插入顺序排序。当缓存的大小超过了其容量时,最久未访问的元素(即链表的尾部元素)会被移除。这样,我们就实现了一个简单的LRU缓存。
面试官: 很好,今天的面试就到这,后续会有人联系你的。