/500-interview-question-for-programmers

This repo is used to record all the good interview questions and answers that I met.

500-interview-question-for-programmers

概述

本代码仓用于记录个人平时面试和学习时碰到的一些有价值的问题,所有问题均为我真实碰到过且思考过(部分附具体面试公司),一律采用问答形式,答案也只是我个人的理解和整理,不一定正确(标记 TODO 为还没来得及弄 Orz...),欢迎指正。

希望以此来保持个人知识体系的扎实性,所以就不是什么基础大全,面试突击,更多是个人对某些问题的总结,可配合同目录下 KnowledgeStructure 同步使用,供所有正在找工作的小伙伴们参考(欢迎 Star,500是一个目标数,切莫抬杠)。

Java

Spring 相关

  • 描述Spring的IoC

    • IoC是一种**,并非一个具体技术
      • 基于 依赖倒置原则(Dependency Inversion Principle)
        • 把原本的高层建筑依赖底层建筑“倒置”过来,变成底层建筑依赖高层建筑。高层建筑决定需要什么,底层去实现这样的需求,但是高层并不用管底层是怎么实现的。这样就不会出现前面的“牵一发动全身”的情况
      • 将原本在程序中手动创建对象的控制权,交由Spring框架来管理
      • 反转 --> 由 IoC容器 来帮忙创建及注入依赖对象(Spring 提供 BeanFactory 和 ApplicationContext 两种容器)
      • 实现 --> 依赖注入(相对 IoC 而言,“依赖注入” 明确描述了 “被注入对象依赖IoC容器配置依赖对象”)
    • 依赖注入,就是 把底层类作为参数传入上层类,实现上层类对下层类的“控制”
      • 谁依赖于谁:当然是应用程序依赖于IoC容器
      • 为什么需要依赖:应用程序需要IoC容器来提供对象需要的外部资源
      • 谁注入谁:很明显是IoC容器注入应用程序某个对象,应用程序依赖的对象
      • 注入了什么:就是注入某个对象所需要的外部资源(包括对象、资源、常量数据)
    • 好处
      • 让你脱离对依赖对象的维护,只需要随用随取,不需要关心依赖对象的任何过程
      • 可以有效地改善模块之间的紧耦合问题
    • 源码实现
      • TODO
    • IoC-spring 的灵魂(带你轻松理解IOC**及bean对象的生成过程)(基本概念)
    • 【第二章】 IoC 之 2.1 IoC基础 ——跟我学Spring3(IoC**详解)
    • Spring IoC有什么好处呢?(汽车的例子有助于理解IoC)
    • Inversion of Control Containers and the Dependency Injection pattern(Martin文章 TODO
    • Spring IOC 容器源码分析(源码阅读 TODO
  • 什么是Bean以及描述Bean的生命周期(美团)

    • 在 Spring 中,构成应用程序主干并由Spring IoC容器管理的对象称为Bean。一个Bean是一个由Spring IoC容器实例化、组装和管理的对象
    • 生命周期
      • 创建Bean
        • 实例化 Bean 对象
        • 设置属性
        • 检查 Aware 相关接口并注入依赖(具体包括 BeanNameAware、BeanFactoryAware 和 ApplicationContextAware,分别注入Bean ID, Bean Factory 或 ApplicationContext)
        • 调用 BeanPostProcessor 的前置初始化方法 postProcessBeforeInitialization
        • 如果实现了 InitializingBean 接口,则会调用 afterPropertiesSet 方法
        • 调用 Bean 自身定义的 init 方法
        • 调用 BeanPostProcessor 的后置初始化方法 postProcessAfterInitialization
        • 创建过程完毕
      • 销毁
        • Spring Bean 的销毁过程会依次调用 DisposableBean 的 destroy 方法和 Bean 自身定制的 destroy 方法
    • Spring Bean是什么?
    • 第37讲 | 谈谈Spring Bean的生命周期和作用域?
  • 描述Spring的AOP(小红书)

    • AOP的理念
      • 将分散在各个业务逻辑代码中 相同的代码 通过 横向切割 的方式抽取到一个独立的模块中(模块化)
      • 将相同逻辑的重复代码横向抽取出来,使用动态代理技术将这些重复代码织入到目标对象方法中,实现和原来一样的功能
    • 基本概念
      • 通知(advice) --> 切面的工作被称为通知,定义了切面是什么以及何时被使用
      • 连接点(join point) --> 应用执行过程中能够插入切面的一个点,可以是方法调用时,抛出异常时等等
      • 切点(pointcut) --> 需要应用切面的方法(具体定位的连接点)
      • 切面(aspect) --> 切面是 通知 和 切点 的结合,共同定义:是什么,在何时和何处完成其功能
      • 织入(weaving) --> 把切面应用到目标函数的过程
    • 好处
      • 显示地声明在何处如何应用该行为,有效减少代码冗余,让类更加关注自身主要功能
    • Spring AOP 具体实现(源码级别) TODO
      • Java JDK 动态代理 (默认)
      • CGLIB 动态代理
    • 关于 Spring AOP (AspectJ) 你该知晓的一切(AOP入门 + 应用场景 + Spring中的基本实现)
    • 《Spring设计**》AOP设计基本原理(从程序运行角度解释AOP的工作原理)
    • 《Spring实战(第四版)》第四章
    • Spring AOP就是这么简单啦(可在面试前看的纯干货)
    • 《Spring设计**》AOP实现原理(基于JDK和基于CGLIB) (Spring AOP的完整实现过程 TODO
  • 简述Spring Boot框架

    • 核心
      • 自动配置
      • 起步依赖
    • 从本质上来说,Spring Boot就是Spring,它做了那些没有它你自己也会去做的Spring Bean配置
    • 《Spring Boot实战》前三章
  • 描述一个Spring Boot项目的启动过程(阿里)

  • 什么是JPA

  • 什么是Spring注解,以及Spring中有哪些常用的注解,以及注解是如何实现的(阿里/头条) TODO

Java语言相关

集合框架

Java内存模型

  • 描述Java内存模型(阿里/美团)

    • JVM内存区域划分
      • 程序计数器(PC, Program Counter Register) --> 它的作用可以看做是当前线程所执行的字节码的行号指示器

      • 虚拟机栈(Virtual Machine Stack) --> 保存一个个栈帧(Stack Frame),对应着一次次的Java 方法调用

      • 本地方法栈(Native Method Stack) --> 和虚拟机栈类似,区别为虚拟机栈为虚拟机执行Java方法(也就是字节码)服务,而本地方法栈为虚拟机使用到的Native方法服务

        ⬆️(线程私有)--- (线程共享) ⬇️

      • 堆(Heap) --> 所有线程共享的内存区域,几乎所有的 对象实例 都在这里分配内存

      • 方法区(Method Area) --> 所有线程共享的一块内存区域,用于存储所谓的元(Meta)数据,如类结构信息,以及对应的运行时常量池、字段、方法代码等

      • 运行时常量池(Run-Time Constant Pool) --> 属于方法区的一部分,存放各种常量信息

    • 第25讲 | 谈谈JVM内存区域的划分,哪些区域可能发生OutOfMemoryError?
    • Java 内存区域详解
    • The Structure of the Java Virtual Machine(官方 Docs TODO
  • 描述Java的GC过程(DaoCloud/美团)

    • 对象存活判断
      • 引用计数(Python 的 GC),无法解决对象相互循环引用的问题,Java中没有使用(Python GC有应用)
      • 可达性分析(GC Roots --> 虚拟机栈和本地方法栈中正在引用的对象、静态属性引用的对象和常量)
    • 垃圾收集算法
      • 标记-清除算法(Mark-Sweep) --> 内存碎片化问题
      • 复制算法(Copying) --> 将内存分为大小相同的两块,每次使用其中的一块。每次将活着的对象复制到 to 区域,拷贝过程中将对象顺序放置,避免内存碎片化
      • 标记-整理算法(Mark-Compact) --> 类似于标记-清除,但为了避免内存碎片化,在清理过程中移动对象,以确保移动后的对象占用连续的内存空间
      • 分代收集算法 --> 根据对象存活周期的不同将内存分为几块(eg: 新生代/老生代)
    • jvm系列(三):GC算法 垃圾收集器
    • JVM 垃圾回收
  • 描述JVM中常见的垃圾回收器,如CMS,以及JVM调优思路(美团)TODO

  • Java对象在内存中是如何存储的(阿里)TODO

  • 浅拷贝 & 深拷贝(头条)

  • 值传递 & 引用传递

    • Java中方法参数传递方式是按值传递
    • 如果参数是基本类型,传递的是基本类型的字面量值的拷贝
    • 如果参数是引用类型,传递的是该参量所引用的对象在堆中地址值的拷贝
    • 什么是值传递和引用传递?

Java并发编程 TODO

  • 描述Java下的并发编程(阿里)

    • Java中实现并发编程的手段 --> 多线程
    • 线程的生命周期(新建 / 就绪 / 运行 / 阻塞 / 死亡)
    • 创建线程的方法
      • Runnable接口
      • 继承Thread
      • 通过 Callable 和 Future 创建线程
    • Java 多线程编程
  • 什么是线程安全

    • 指某个函数、函数库在多线程环境中被调用时,能够正确地处理多个线程之间的共享变量,使程序功能正确完成
    • a class is thread safe when it continues to behave correctly when accessed from multiple threads
    • 线程安全 Wiki
  • synchronized 和 ReentrantLock

  • volatile关键字(阿里)

    • 保证变量的可见性(指示 JVM,这个变量是不稳定的,每次使用它都到主存中进行读取) & 防止指令重排序
    • 只能用于变量
    • 对一个 volatile 变量的写操作, Happens-Before 后续对这个 volatile 变量的读操作
    • 2. volatile关键字
  • Java中如何使用线程池(阿里)

  • 乐观锁与悲观锁的概念,常见实现(阿里)

    • 乐观锁适用于多读的应用类型,这样可以提高吞吐量 / 悲观锁适合于多写
    • 乐观锁常见实现 --> 版本号机制 / CAS 算法
      • CAS 算法概念 / 缺点
        • ABA 问题
    • 何谓悲观锁与乐观锁
    • Compare-and-swap Wiki
  • join() 方法有什么用

  • 描述 Atomic 类的底层实现(美团)TODO

  • 描述 ThreadLocal 类 (美团)TODO

  • 并发学习资源

Python

  • 用map/reduce实现数组求和(PayPal)

    • map --> 将传入函数依次作用于序列中的每个元素,并把结果作为新的Iterator返回;
    • reduce --> 累积计算, 求和 reduce(lambda x, y : x + y, [1,2,3,4,5]).
    • map/reduce
  • 实现一个lambda表达式(头条)

  • Python如何实现真正的多线程(阿里/腾讯) TODO

  • 给一段Python代码,有哪些优化思路和策略(阿里)TODO

  • 如何写一个程序计算一段Python代码的耗时(腾讯)TODO

  • Python爬虫中存在环引用该如何处理(阿里)TODO

  • 描述Python的迭代器和生成器(DaoCloud) TODO

操作系统

数据结构和算法

排序相关

链表/数组/栈/队列

  • 反转链表(小红书/腾讯/头条)

  • 复杂链表的复制

    • 连接一个重复链表
    • 断链,拆分成两个链表(清楚断链的操作是什么)
    • 复杂链表的复制

字符串

  • 如何找出一个字符串中的最大不重复子串(蜻蜓FM/美团)

    • 暴力求解 --> 逐个遍历,找最长子串(设置一个 allUnique 函数)/ O(n^3)
    • 滑动窗口 --> 滑动窗口直到最后一个元素,每当碰到重复左指针往后走,否则右指针往后走,同时比较 / O(n)
    • 3. 无重复字符的最长子串
  • 字符串的排列

    • 理解递归结构的构造过程(固定一个字符,继续处理剩余字符)
    • 是对一个确定的初始字符串进行操作,得到一个结果后通过需要换回来
    • 字符串的排列

动态规划

其他算法题

笔试真题快照

  • 拼多多学霸批服务端 0728

      1. 严格升序数组替换
      • 需要考虑替换哪一个数,逆序对需要全部提取出来,而不是仅仅考虑逆序对中小的那个,如:1, 3, 8, 7, 10, 替换8或者替换7都有可能(可以先考虑替换n+1,因为是选较大的数,不满足再替换n)
      • 同时还要考虑首尾情况,如:10,5,6,7,8,9,就只能替换10了
      1. 数组中单词首尾能否成环
      • 深度优先搜索(DFS) + 回溯法
      • 个人思路 (不适用于存在多个配对的情况)
        • judge(list, i, k, cur, flag[])
        • 首元素flag记为2,访问过记为1,最后一个元素与 flag==2 对应的字符串做判断
        • 剩下flag未遍历过的元素中找
      1. 任务优先级排序,任务间存在依赖关系,给出最优(累加时间最少)方案
      • 用小顶堆存储当前可执行的任务
      • 每次出堆后更新依赖
      • 把依赖为0的任务当做可执行任务入堆(维护一个依赖01数组)
      1. 堆积木,求积木的最高高度,要求下层积木体积必须大于上层,且某块积木上层的重量之和不能超过本身的7倍
      • 动态规划
      • dp[i][h]记录以第i块积木为底, 高为h的积木塔的最低重量
      • dp[i][h] = nodes[i].w + dp[j][h-1](j 从 i-1 开始遍历)
    • 拼多多学霸批算法工程师笔试题经验
  • 头条后端开发笔试 0811

数据库

数据库理论

  • 描述事务隔离的级别(野村证券/远景智能)

    • Serializable(序列化) --> 可避免脏读,不可重复读,幻读
    • Repeatable read(可重复读) --> 可避免脏读,不可重复读,但可能出现幻读
    • Read committed(已提交读) --> 可避免脏读,但是可能会造成不可重复读
    • Read uncommitted(未提交读) --> 级别最低,什么都避免不了
    • 脏读 --> 当一个事务允许读取另外一个事务修改但未提交的数据时,就可能发生脏读
    • 不可重复度 --> 在一次事务中,当一行数据获取两遍得到不同的结果表示发生了“不可重复读”
    • 幻读 --> 在事务执行过程中,当两个完全相同的查询语句执行得到不同的结果集。这种现象称为幻读
    • ACID Wiki
    • 事务隔离 Wiki
    • 数据库事务隔离级别-- 脏读、幻读、不可重复读(清晰解释)
  • MySQL是如何实现隔离级别的(如可重复读的实现原理)(拼多多) TODO

  • delete、 drop、truncate 的区别(PayPal)

    • drop 直接删掉表(不再需要一张表的时候,用drop)
    • truncate 删除的是表中的数据,再插入数据时自增长的数据id又重新从1开始(保留表而删除所有数据的时候用truncate,实际是删除原来的表并重建一张新表)
    • delete 删除表中数据,可以在后面添加where字句(想删除部分数据行时候,用delete,并且带上where子句)
    • SQL truncate 、delete与drop区别
  • 第一/第三/BC范式,以及我们实际建表时为什么要设计冗余字段,同时设计冗余字段会带来什么问题(阿里)

索引

SQL语句相关

计算机网络

Linux相关

常见Linux指令 TODO

  • top,load 指令,free 中 cached和buffers的区别(阿里)
  • 找出某目录下文件中带电子邮箱的文件(爱奇艺)
  • 杀死所有Java进程

编程之美

设计模式

  • 简述设计模式

  • 实现一个线程安全的单例模式

    • 懒汉模式 --> Lazy初始化
    • 饿汉模式 --> 在方法调用前,实例就已经创建好了
    • 全部 sychronized 锁住 --> 可以保证线程安全,但销效率低
    • “双重检查锁” 机制版本 (面试用这个)
      • volatile 来保证其线程间的可见性,禁止指令重排序,保证返回的是初始化完全的对象
      • 同步代码块中使用二次检查,以保证其不被重复实例化
    • 枚举enum和静态代码块的特性相似,在使用枚举时,构造方法会被自动调用,利用这一特性也可以实现单例(面试可稍微提及)
    • 高并发下线程安全的单例模式(最全最经典) (单例的N种实现)
    • 单例模式(详尽介绍)
    • Why is volatile used in double checked locking

设计/架构

场景题

  • 一个任务序列执行顺序如 A --> B1,B2,B3 --> C,如何保证该任务执行先后顺序的准确性(拼多多)

    • 使用 CountDownLatch --> 可以让线程等待其它线程完成一组操作后才能执行,否则就一直等待
    • CountDownLatch详解
  • 如何设计一个秒杀系统(小红书)

  • 高并发访问下如何保证用户名不冲突,比如多个用户同时创建同一个用户名(拼多多)TODO

  • 设计一个方案,提供不同算法调用接口(参数即为需要调用的方法名)(设计模式实际应用)(PayPal)

    • 这题感觉非常开放,我当时答了用 适配器模式,似乎面试官并不是特别满意,感觉 适配器模式 属于结构型模式,主要用于解决兼容性问题,实际此题还是以如何创建为主,用 工厂模式 为宜
    • 工厂模式 (定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行) --> 传入方法参数,实例化具体对象
    • 两道设计模式的面试题
    • 工厂模式
  • 设计一个方案,传入一个类型(如 圆形,矩形,三角形等),求对应的周长和面积,用设计模式更好(头条)

    • 工厂模式,传入Shape 和一个用于保存参数的Map(或者别的存储方式?)
    • 工厂模式
  • 结合项目,权限管理是如何设计的(星环科技) TODO

  • 谈一下synchronized 和 wait() 搭配使用的场景(星环科技)

  • 设计一个表结构,用于记录高考之后学生的成绩,以及写一个查询得到某个城市的理科前十名(头条)TODO

工具类

  • kafka TODO

    • 基于发布-订阅模式(publish-subscribe)
    • 术语
      • topic
        • A topic is a category or feed name to which records are published
      • partition
        • Each partition is an ordered, immutable sequence of records that is continually appended to a structured commit log
        • offset
    • 特征
      • stronger ordering guarantees ("exclusive consumer")
    • kafka Stream
  • redis TODO

其他

  • git rebase 和 git merge 有什么区别(小红书/野村证券/PayPal)

    • 同:都是用于从一个分支获取并且合并到当前分支
    • 异:rebase --> 会合并之前的commit历史(带有破坏性的修改 commit 历史的命令)
    • 一个干净的,没有merge commit的线性历史树 --> git rebase
    • 保留完整的历史记录,并且想要避免重写commit history的风险 --> git merge
    • git rebase 和 git merge 的区别
  • git fetch 和 git pull 有什么区别(PayPal)

  • 描述 git 中的 cherry-pick 指令(小红书)TODO

  • 描述微服务架构(携程) TODO