【Java基础面试题】—— 核心知识点面试题(含答案):语法+集合+JVM+设计模式+算法

Java/Python 核心知识点面试题(含答案):语法+集合+JVM+设计模式+算法

一、语法基础(Java/Python 通用 + 各自重点)

(一)通用语法
  1. Java 和 Python 的核心区别是什么?
  • 类型:Java 静态类型(编译时检查),Python 动态类型(运行时检查);

  • 运行方式:Java 编译为字节码(.class),JVM 解释执行;Python 源码编译为字节码(.pyc),解释器逐行执行;

  • 性能:Java 性能更高(静态类型 + JIT 优化),Python 稍弱(GIL 影响并发);

  • 应用场景:Java 适用于后端、大数据、安卓;Python 适用于 AI、脚本、数据分析。

  1. 面向对象的三大特性?举例说明。
  • 封装:隐藏对象内部细节,通过方法暴露接口(如 Java 的 private 字段 +getter/setter);

  • 继承:子类复用父类属性和方法(如 class Dog extends Animal,Dog 继承 Animal 的 eat() 方法);

  • 多态:同一方法不同实现(如 Animal 的 makeSound(),Dog 实现为 "汪汪",Cat 实现为 "喵喵")。

  1. 重载(Overload)和重写(Override)的区别?Python 支持重载吗?
  • 重载:同一类中,方法名相同、参数列表(类型 / 个数 / 顺序)不同,编译时绑定;

  • 重写:子类覆盖父类同名方法,参数列表一致,运行时绑定;

  • Python 不支持传统重载(后定义的方法会覆盖前一个),可通过默认参数 /*args 模拟。

  1. 接口和抽象类的区别?Java 8 中接口的新特性?
  • 抽象类:可含抽象方法 + 普通方法,有构造器,只能单继承;

  • 接口:Java 8 前仅抽象方法 + 常量,无构造器,支持多实现;

  • Java 8 接口新特性:支持默认方法(default 修饰,有实现)、静态方法(static 修饰)。

  1. 什么是泛型?Java 和 Python 泛型的区别?
  • 泛型:定义时不指定具体类型,使用时指定,实现代码复用(如 Java ListList[int]);

  • Java 泛型:编译时擦除(本质是 Object 强制转换),仅编译期类型检查;

  • Python 泛型(Type Hint):仅语法提示,运行时不生效(如 def func(x: int) -> str,x 仍可传字符串)。

(二)Java 语法重点
  1. 基本数据类型和包装类的区别?自动装箱 / 拆箱问题?
  • 基本类型:8 种(int/char 等),栈存储,无方法;包装类:对应引用类型(Integer/Character),堆存储,有方法;

  • 自动装箱:基本类型 → 包装类(如 int → Integer);拆箱:包装类 → 基本类型(如 Integer → int);

  • 问题:Integer a=127, b=127 相等(缓存 [-128,127]),a=128, b=128 不相等(新对象);包装类为 null 时拆箱会抛 NPE。

  1. final、finally、finalize 的区别?
  • final:修饰类(不可继承)、方法(不可重写)、变量(不可修改);

  • finally:try-catch 后必执行(除非 JVM 退出),用于释放资源;

  • finalize:Object 类方法,GC 回收对象前调用,不可靠(不保证执行),已废弃。

  1. static 关键字的作用?
  • 静态变量:类共享,不属于实例,随类加载初始化;

  • 静态方法:无 this 指针,不能访问非静态成员,可直接通过类名调用;

  • 静态代码块:类加载时执行一次,用于初始化静态资源;

  • 静态内部类:不依赖外部类实例,不能访问外部类非静态成员。

  1. 异常体系与 try-catch-finally 执行顺序?
  • 体系:Throwable 是父类,子类为 Error(系统错误,不可处理)和 Exception(可处理);

  • checked exception:编译时检查(如 IOException),必须捕获或抛出;unchecked exception:运行时异常(如 NullPointerException),无需强制处理;

  • 执行顺序:try → 异常时执行 catch → 无论是否异常,finally 必执行(return 前执行,finally 中 return 会覆盖 try/catch 的 return)。

  1. Lambda 表达式与函数式接口?
  • Lambda 语法:(参数) -> 表达式/代码块(如 (a,b) -> a+b),简化匿名内部类;

  • 函数式接口:仅含一个抽象方法的接口(如 RunnableComparator),可通过 @FunctionalInterface 注解校验。

  1. Stream API 的优缺点?
  • 常用操作:过滤(filter)、映射(map)、聚合(reduce)、排序(sorted);

  • 优点:代码简洁、支持链式调用、并行流(parallelStream)利用多核;

  • 缺点:并行流需注意线程安全(如非线程安全集合的 forEach),调试困难。

(三)Python 语法重点
  1. 解释器工作原理与 GIL?
  • 原理:Python 是解释型语言,源码 → 字节码(.pyc)→ 解释器(CPython)执行;

  • GIL(全局解释器锁):CPython 特有,同一时刻仅一个线程执行 Python 字节码,多核下并发变串行,IO 密集型(如网络请求)影响小,CPU 密集型(如计算)影响大。

  1. 装饰器、生成器、迭代器的原理?
  • 装饰器:函数嵌套,包装目标函数,增强功能(如日志、计时),用 @decorator 语法;带参数装饰器需三层嵌套(如 def decorator(param): def wrapper(func): ... return wrapper);

  • 生成器:含 yield 关键字的函数,执行到 yield 暂停,返回迭代器,节省内存(如 def gen(): yield 1; yield 2);

  • 迭代器:实现 __iter__()__next__() 方法的对象,可通过 next() 逐个获取元素(如 list 的迭代器)。

  1. 深拷贝与浅拷贝的区别?
  • 浅拷贝:复制对象引用,子对象共享(如 copy.copy(list),列表元素为对象时,仅复制对象地址);

  • 深拷贝:递归复制对象及子对象,完全独立(如 copy.deepcopy(list));

  • 注意:不可变对象(tuple/str)的浅拷贝等于本身。

  1. 闭包的定义与条件?
  • 定义:内层函数引用外层函数的变量,外层函数返回内层函数;

  • 条件:内层函数嵌套外层函数、内层函数引用外层函数变量、外层函数返回内层函数;

  • 问题:外层变量若为可变类型(如 list),多次调用可能共享状态。

  1. Python 的垃圾回收机制?
  • 核心:引用计数为主(对象被引用一次计数 + 1,引用消失 - 1,计数为 0 回收);

  • 辅助机制:分代回收(新生代 / 老年代,新生代回收频繁)、标记清除(解决循环引用,如 a=b, b=a)。

  1. 字典(dict)的底层实现?Python 3.7+ 为何有序?
  • 底层:哈希表(数组 + 链表),键通过哈希函数映射到数组索引,查找时间复杂度 O (1);

  • 有序原因:Python 3.7+ 用双向链表记录插入顺序,数组存储链表节点指针,遍历按链表顺序。

  1. __init__ __new__ __del__的区别?
  • __new__:创建对象时调用,返回对象实例(构造方法),可用于单例模式;

  • __init__:初始化对象时调用,接收参数给实例赋值(初始化方法);

  • __del__:对象被 GC 回收时调用(析构方法),用于释放资源,不可靠。


二、集合框架(Java/Python 对应对比)

(一)Java 集合框架

  1. 集合框架结构与 List/Set/Map 区别?
  • 结构:两大体系 ------Collection(存储单元素,如 List/Set)和 Map(存储键值对,如 HashMap);

  • 区别:List(有序、可重复,如 ArrayList)、Set(无序、不可重复,如 HashSet)、Map(键唯一、值可重复,如 HashMap)。

  1. ArrayList 和 LinkedList 的区别?
特性 ArrayList(动态数组) LinkedList(双向链表)
查找效率 O (1)(随机访问) O (n)(遍历查找)
插入删除效率 O (n)(需移动元素) O (1)(仅改指针,已知位置)
内存占用 连续空间,浪费少 额外存储指针,浪费多
适用场景 高频查询、少量插入删除 高频插入删除、少量查询
  1. HashMap 的底层原理(JDK 1.7 vs 1.8)?
  • JDK 1.7:数组 + 链表,哈希冲突用链地址法(链表头插);

  • JDK 1.8:数组 + 链表 + 红黑树(链表长度 > 8 且数组容量≥64 时转红黑树,化为链表);

  • 扩容机制:初始容量 16,负载因子 0.75,扩容阈值 = 容量 × 负载因子,扩容时容量翻倍(重新哈希);

  • 线程不安全:多线程扩容时可能出现链表循环;ConcurrentHashMap 线程安全:JDK 1.7 用分段锁,JDK 1.8 用 CAS+Synchronized(锁数组节点)。

  1. HashSet 的底层实现与去重原理?
  • 底层:基于 HashMap,值存储在 HashMap 的 key 中(value 为固定空对象 PRESENT);

  • 去重:依赖 HashMap 的 key 唯一性(key 的 hashCode()equals() 方法),若两对象 hashCode 相等且 equals 为 true,则视为同一 key。

  1. TreeMap/TreeSet 的底层实现与排序?
  • 底层:红黑树(平衡二叉查找树),保证有序;

  • 排序:自然排序(实现 Comparable 接口,重写 compareTo())或定制排序(传入 Comparator 接口实现类)。

  1. Vector 和 ArrayList 的区别?
  • 线程安全:Vector 线程安全(方法加 synchronized),ArrayList 线程不安全;

  • 扩容机制:Vector 初始容量 10,默认扩容翻倍;ArrayList 初始容量 10,默认扩容 1.5 倍。

  1. 迭代器的 fail-fast 和 fail-safe 区别?
  • fail-fast(快速失败):如 ArrayList 的迭代器,遍历中修改集合(增删)会抛 ConcurrentModificationException(通过 modCount 校验);

  • fail-safe(安全失败):如 CopyOnWriteArrayList 的迭代器,遍历前复制集合快照,修改原集合不影响快照,无异常,但可能读取旧数据。

(二)Python 集合框架

  1. list/tuple/set/dict 的核心区别?
特性 list(列表) tuple(元组) set(集合) dict(字典)
可变性 可变 不可变 可变 可变
有序性 有序(3.7+) 有序 无序 有序(3.7+)
查找效率 O(n) O(n) O(1) O(1)
适用场景 有序存储 不可变数据 去重 / 交集 键值对查询
  1. list 的底层与 append/extend 区别?
  • 底层:动态数组,预分配容量,满了自动扩容(默认扩容 1.125 倍左右);

  • append:添加单个元素(如 list.append(1));extend:添加可迭代对象的所有元素(如 list.extend([2,3]))。

  1. dict 查找 O (1) 的原因与哈希冲突解决?
  • O (1) 原因:键通过哈希函数映射到数组索引,直接访问索引;

  • 哈希冲突:多个键映射到同一索引,用开放寻址法(线性探测 / 二次探测)解决(CPython 实现)。

  1. set 的底层与去重原理?
  • 底层:哈希表,存储唯一元素,无键值对;

  • 去重:元素必须可哈希(不可变类型,如 int/str/tuple),通过哈希值和 __eq__ 方法判断唯一性;

  • 交集 / 并集:a & b(交集)、a | b(并集),基于哈希表快速计算。

  1. tuple 比 list 高效的原因?tuple 真的不可变吗?
  • 高效原因:不可变,内存分配更紧凑,无需预留扩容空间;

  • 不可变限制:仅顶层元素不可变,若元素为可变类型(如 list),则元素内部可修改(如 t = (1, [2]); t[1].append(3) 有效)。

  1. OrderedDict 和普通 dict 的区别?
  • Python 3.7+ 普通 dict 已有序,OrderedDict 额外特性:

    • 支持 move_to_end() 移动元素到首尾;

    • 支持按插入顺序或访问顺序排序;

    • 相等性判断考虑顺序(普通 dict 不考虑,如 {1:2,3:4} == {3:4,1:2} 为 True)。

(三)通用对比问题

  1. Java ArrayList vs Python list?
  • 底层:均为动态数组;

  • 性能:Java 效率更高(静态类型 + 数组存储基本类型),Python list 存储引用,效率稍低;

  • 功能:Python list 支持动态添加不同类型元素(如 [1, "a"]),Java ArrayList 仅支持单一类型(泛型限制)。

  1. Java HashMap vs Python dict?
  • 哈希冲突:HashMap 用链地址法,dict 用开放寻址法;

  • 扩容:HashMap 扩容翻倍,dict 扩容为原容量的 2~4 倍;

  • 有序性:HashMap 无序(Java 8 后链表有序但遍历无序),Python 3.7+ dict 有序。

  1. 集合选择场景?
  • 有序存储 + 高频查询:Java ArrayList / Python list;

  • 无序去重 + 高频查找:Java HashSet / Python set;

  • 键值对查询:Java HashMap / Python dict;

  • 有序键值对 + 排序:Java TreeMap / Python OrderedDict(或普通 dict + 排序)。


三、JVM 内存模型与 GC 机制(Java 重点)

  1. JVM 运行时数据区结构?
  • 程序计数器:存储当前线程执行指令地址,线程私有,无 OOM;

  • 虚拟机栈:线程私有,存储栈帧(局部变量表、操作数栈等),栈深度过大抛 StackOverflowError,扩容失败抛 OOM;

  • 本地方法栈:类似虚拟机栈,为 native 方法服务;

  • 方法区:存储类元信息、常量、静态变量,JDK 8 后为元空间(本地内存),JDK 7 及以前为永久代(堆内存),满了抛 OOM;

  • 堆:线程共享,存储对象实例,JVM 最大内存区域,满了抛 OOM。

  1. 堆内存划分与 GC 策略?
  • 划分:年轻代(Eden 区 + Survivor 区 S0/S1,比例 8:1:1)、老年代;

  • 策略:年轻代用复制算法(Eden 区满触发 Minor GC,存活对象复制到 S0/S1,多次存活后进入老年代);老年代用标记 - 整理算法(空间碎片少),Full GC 触发时回收老年代 + 年轻代。

  1. OOM 常见场景与解决方案?
  • 堆溢出(OutOfMemoryError: Java heap space):对象过多且无法回收,解决方案:增大堆内存(-Xms/-Xmx)、排查内存泄漏(如静态集合持有对象);

  • 栈溢出(StackOverflowError):递归过深或栈帧过大,解决方案:增大栈容量(-Xss)、优化递归(改为迭代);

  • 方法区 / 元空间溢出:类加载过多(如频繁动态生成类),解决方案:增大元空间(-XX:MetaspaceSize)、减少无用类加载。

  1. 对象可回收判断方式?
  • 引用计数法:简单但无法解决循环引用(如 a=b, b=a);

  • 可达性分析:以 GC Roots(如线程栈局部变量、静态变量)为起点,遍历对象引用链,不可达对象标记为可回收。

  1. 四大引用类型区别与应用?
类型 特点 应用场景
强引用 不回收,OOM 也不释放 普通对象引用(Object o=new Object()
软引用 内存不足时回收 缓存(如 SoftReference 包装缓存对象)
弱引用 GC 时立即回收 临时数据(如 WeakHashMap 键)
虚引用 仅用于跟踪 GC,无实际引用 堆外内存回收(如 PhantomReference
  1. GC 算法原理与优缺点?
  • 标记 - 清除:标记可回收对象,直接清除,优点:简单,缺点:产生内存碎片;

  • 标记 - 复制:将内存分为两块,存活对象复制到另一块,优点:无碎片,缺点:浪费一半内存(年轻代适用);

  • 标记 - 整理:标记后将存活对象移到一端,清除剩余部分,优点:无碎片,缺点:移动对象开销大(老年代适用);

  • 分代收集:结合以上算法,年轻代用复制,老年代用标记 - 整理,平衡效率与碎片。

  1. 主流 GC 收集器特点?
  • SerialGC:单线程收集,简单高效,适用于单核心、小内存场景;

  • ParallelGC:多线程收集,注重吞吐量(GC 时间 / 总时间占比),适用于后台任务;

  • CMS:并发标记清除,低延迟(GC 时用户线程不暂停),流程:初始标记(STW)→ 并发标记 → 重新标记(STW)→ 并发清除;缺点:产生碎片、占用 CPU 资源;

  • G1:分区回收(将堆分为多个 Region),兼顾吞吐量与延迟,支持预测性 GC,流程:初始标记 → 并发标记 → 最终标记 → 筛选回收(STW,回收价值最高的 Region);

  • ZGC/Shenandoah:超低延迟(暂停时间 < 10ms),适用于大内存、低延迟场景。

  1. JVM 调优核心指标与参数?
  • 核心指标:吞吐量(优先)、延迟(优先);

  • 常用参数:

    • 堆大小:-Xms2G(初始堆)、-Xmx2G(最大堆),建议两者相等避免频繁扩容;

    • 新生代比例:-XX:NewRatio=2(老年代:新生代 = 2:1);

    • 收集器选择:-XX:+UseG1GC(启用 G1)、-XX:+UseConcMarkSweepGC(启用 CMS);

    • GC 日志:-XX:+PrintGCDetails -Xloggc:gc.log(输出 GC 日志)。

  1. 类加载机制与生命周期?
  • 生命周期:加载 → 验证 → 准备 → 解析 → 初始化 → 使用 → 卸载;

  • 加载:通过类全限定名获取字节码,生成 Class 对象;

  • 准备:为静态变量分配内存并设置默认值(如 static int a=1 此时为 0,初始化时赋值 1);

  • 初始化:执行静态代码块和静态变量赋值,触发条件:new 对象、调用静态方法 / 变量、反射、子类初始化。

  1. 双亲委派模型原理与作用?如何打破?
  • 原理:类加载器(Bootstrap → Extension → Application)加载类时,先委托父加载器加载,父加载器无法加载再自己加载;

  • 作用:防止类重复加载、保护核心类(如 java.lang.String 不能被自定义类替换);

  • 打破方式:重写 ClassLoaderloadClass() 方法(如 Tomcat 类加载器,为每个 Web 应用单独加载类)。


四、常用设计模式

  1. 设计模式六大原则?
  • 单一职责:一个类只负责一个功能(如 UserService 只处理用户相关逻辑);

  • 开闭原则:对扩展开放,对修改关闭(如用接口扩展功能,而非修改原有代码);

  • 里氏替换:子类可替换父类,不改变原有逻辑(如子类不能重写父类的 final 方法);

  • 依赖倒置:依赖抽象(接口 / 抽象类),不依赖具体实现(如依赖 Logger 接口,而非 FileLogger 实现类);

  • 接口隔离:接口拆分细小,避免实现不需要的方法(如将大接口拆分为多个小接口);

  • 迪米特法则:最少知道原则,一个对象只与直接关联对象通信(如减少类之间的依赖)。

  1. 单例模式的实现方式?
  • 饿汉式:类加载时初始化实例,线程安全,缺点:提前占用内存(private static final Singleton INSTANCE = new Singleton());

  • 懒汉式:延迟初始化,线程不安全(需加 synchronized 优化,效率低);

  • 双重检查锁:线程安全且高效(volatile 修饰实例,防止指令重排:private static volatile Singleton INSTANCE;);

  • 静态内部类:线程安全,延迟加载(内部类加载时初始化实例);

  • 枚举:最简单,线程安全,防止反射破坏(enum Singleton { INSTANCE; })。

  1. 工厂模式的区别?
  • 简单工厂:一个工厂类创建所有对象,缺点:违反开闭原则(新增产品需修改工厂);

  • 工厂方法:每个产品对应一个工厂类,实现工厂接口,符合开闭原则(新增产品只需新增工厂);

  • 抽象工厂:创建一系列相关产品(产品族),如创建 "手机 + 电脑" 套装,缺点:扩展产品族需修改抽象工厂接口。

  1. 代理模式的实现与区别?
  • 静态代理:手动编写代理类,实现目标接口,缺点:重复代码多(每个目标类需对应代理类);

  • 动态代理:运行时生成代理类,JDK 动态代理(基于接口,需目标类实现接口)、CGLIB 动态代理(基于子类,无需实现接口,需依赖 CGLIB 库);

  • 与装饰器模式区别:代理模式侧重 "控制访问"(如权限校验),装饰器模式侧重 "增强功能"(如添加日志)。

  1. 装饰器模式的应用?
  • 原理:包装目标对象,动态添加功能,不改变原类结构(如 Java 的 BufferedReader 装饰 Reader,添加缓冲功能);

  • Python 示例:用装饰器为函数添加计时功能(@timeit)。

  1. 观察者模式的原理?
  • 定义:观察者订阅被观察者,被观察者状态变化时通知所有观察者(如订阅公众号,公众号更新推送给订阅者);

  • Java 实现:Observable 类(被观察者)、Observer 接口(观察者),Observable 调用 notifyObservers() 通知观察者。

  1. 策略模式的应用?
  • 原理:定义算法族,封装成独立类,可动态切换(如排序算法族:快速排序 / 归并排序,根据场景切换);

  • 优化多条件判断:如 if (type == 1) 快速排序; else if (type == 2) 归并排序; 改为策略模式,新增算法无需修改判断逻辑。

  1. 适配器模式的区别?
  • 类适配器:继承目标类和适配者类,缺点:单继承限制;

  • 对象适配器:持有适配者对象,组合方式,更灵活(推荐);

  • 应用:将旧接口适配新接口(如将 LegacyService 适配 NewService 接口)。

  1. 建造者模式与工厂模式的区别?
  • 建造者模式:侧重复杂对象的分步构建(如 StringBuilder 分步 append 构建字符串),关注 "构建过程";

  • 工厂模式:侧重对象的创建,不关注构建过程,直接返回成品。

  1. 项目中常用的设计模式?
  • 单例模式:配置类(如 Config.getInstance())、工具类(如 Logger);

  • 工厂模式:对象创建(如 UserFactory.createUser());

  • 代理模式:权限校验、日志记录(如 Spring AOP 基于动态代理);

  • 装饰器模式:功能增强(如 Spring 的 BeanWrapper);

  • 策略模式:动态切换算法(如支付方式选择:微信支付 / 支付宝支付)。


五、数据结构与算法

(一)基础数据结构

  1. 数组和链表的区别?
  • 存储:数组连续内存,链表非连续(节点 + 指针);

  • 查找:数组 O (1)(随机访问),链表 O (n);

  • 插入删除:数组 O (n)(移动元素),链表 O (1)(改指针);

  • 适用场景:数组适合高频查询,链表适合高频插入删除。

  1. 栈和队列的应用?
  • 栈:先进后出(FILO),应用:递归调用栈、表达式求值、括号匹配;

  • 队列:先进先出(FIFO),应用:任务调度、消息队列、BFS 遍历;

  • 实现:栈可用数组 / 链表,队列可用数组(循环队列)/ 链表。

  1. 哈希表的原理?
  • 核心:哈希函数(将键映射到索引)+ 哈希冲突解决(链地址法 / 开放寻址法);

  • 哈希函数设计原则:均匀分布(减少冲突)、计算高效;

  • 应用:缓存(HashMap)、去重(HashSet)。

  1. 二叉查找树(BST)的特点?
  • 特点:左子树所有节点值 节点,右子树所有节点值 > 根节点;

  • 操作:查找 / 插入 / 删除 O (logn)(平衡时),最坏 O (n)(退化为链表);

  • 优化:红黑树 / AVL 树(平衡 BST)。

  1. 红黑树的核心特性?
  • 特性:节点非红即黑、根节点黑、叶子节点(NIL)黑、红节点的子节点黑、任意节点到叶子节点的黑路径长度相等;

  • 优势:平衡二叉树,查找 / 插入 / 删除 O (logn),旋转次数少(比 AVL 树高效),适合作为 TreeMap/TreeSet 底层。

  1. 堆的原理与应用?
  • 原理:完全二叉树,大顶堆(父节点 ≥ 子节点)、小顶堆(父节点 ≤ 子节点);

  • 堆排序步骤:构建堆 → 交换堆顶与堆尾 → 调整堆 → 重复;

  • 应用:优先队列(如 Java 的 PriorityQueue)、Top K 问题(用小顶堆找最大 K 个元素)。

  1. 图的存储与遍历?
  • 存储:邻接矩阵(二维数组,适合稠密图)、邻接表(链表数组,适合稀疏图);

  • 遍历:DFS(深度优先,递归 / 栈实现,适合路径查找)、BFS(广度优先,队列实现,适合最短路径查找)。

(二)核心算法

  1. 排序算法对比?
算法 时间复杂度(平均) 空间复杂度 稳定性 特点
冒泡排序 O(n²) O(1) 稳定 简单,适合小规模数据
选择排序 O(n²) O(1) 不稳定 交换次数少
插入排序 O(n²) O(1) 稳定 适合基本有序数据
快速排序 O(nlogn) O(logn) 不稳定 高效,实际应用广泛
归并排序 O(nlogn) O(n) 稳定 适合大规模数据、外部排序
堆排序 O(nlogn) O(1) 不稳定 无需额外空间
  • 快速排序优化:基准值选中间元素 / 三数取中,避免最坏情况(O (n²));

  • 实际应用:Java Arrays.sort() 对基本类型用双轴快排,对对象用归并排序(保证稳定性)。

  1. 二分查找的实现与注意事项?
  • 原理:有序数组中,每次比较中间元素,缩小查找范围;

  • 迭代实现:left=0, right=n-1; while(left { mid=(left+right)/2; if(target==nums[mid]) return mid; else if(target[mid]) right=mid-1; else left=mid+1; }

  • 注意:避免 mid 溢出(用 mid=left+(right-left)/2 替代 (left+right)/2);重复元素时需调整边界(如找第一个等于 target 的元素)。

  1. 动态规划(DP)的核心思想?
  • 核心:将大问题拆分为小问题,存储小问题答案(避免重复计算),定义状态转移方程;

  • 步骤:定义状态 → 确定转移方程 → 初始化 → 计算结果;

  • 示例:爬楼梯(状态 dp[i] 为第 i 级台阶的走法数,转移方程 dp[i] = dp[i-1] + dp[i-2])。

  1. 贪心算法与动态规划的区别?
  • 贪心:局部最优 → 全局最优(如活动选择问题,选结束时间最早的),适用场景有限(需满足贪心选择性质);

  • 动态规划:全局最优包含局部最优,需存储中间状态(如最长递增子序列),适用更复杂场景。

  1. 回溯算法的应用?
  • 核心:试探性搜索,不满足条件则回溯(如走迷宫);

  • 应用:全排列、组合总和、N 皇后问题、子集问题;

  • 实现:递归 + 剪枝(减少无效搜索,如 N 皇后剪枝同行 / 同列 / 对角线的位置)。

  1. 分治算法的核心思想?
  • 核心:分(拆分为子问题)→ 治(解决子问题)→ 合(合并子问题结果);

  • 应用:归并排序、快速排序、大数乘法、二分查找。

(三)实战编程题(高频手撕)

  1. 反转链表(单链表)

    // Java 实现

    public ListNode reverseList(ListNode head) {

    ListNode prev = null, curr = head;

    while (curr != null) {

    ListNode next = curr.next;

    curr.next = prev;

    prev = curr;

    curr = next;

    }

    return prev;

    }

    # Python 实现

    def reverse_list(head):

    prev, curr = None, head

    while curr:

    next_node = curr.next

    curr.next = prev

    prev, curr = curr, next_node

    return prev

  2. 两数之和(数组)

    public int[] twoSum(int[] nums, int target) {

    Map Integer> map = new HashMap<>();

    for (int i = 0; i ++) {

    int complement = target - nums[i];

    if (map.containsKey(complement)) {

    return new int[]{map.get(complement), i};

    }

    map.put(nums[i], i);

    }

    return new int[]{};

    }

  3. 二分查找(有序数组)

    def binary_search(nums, target):

    left, right = 0, len(nums)-1

    while left = left + (right - left) // 2

    if nums[mid] == target:

    return mid

    elif nums[mid] left = mid + 1

    else:

    right = mid - 1

    return -1

  4. 二叉树层序遍历(BFS)

    public List<List(TreeNode root) {

    List<List res = new ArrayList

    if (root == null) return res;

    Queue queue = new LinkedList

    queue.offer(root);

    while (!queue.isEmpty()) {

    int size = queue.size();

    List new ArrayList for (int i = 0; i i++) {

    TreeNode node = queue.poll();

    level.add(node.val);

    if (node.left != null) queue.offer(node.left);

    if (node.right != null) queue.offer(node.right);

    }

    res.add(level);

    }

    return res;

    }

  5. 全排列(回溯)

    def permute(nums):

    res = []

    def backtrack(path, used):

    if len(path) == len(nums):

    res.append(path.copy())

    return

    for i in range(len(nums)):

    if used[i]:

    continue

    used[i] = True

    path.append(nums[i])

    backtrack(path, used)

    path.pop()

    used[i] = False

    backtrack([], [False]*len(nums))

    return res

  6. LRU 缓存实现(哈希表 + 双向链表)

    class LRUCache {

    class Node {

    int key, val;

    Node prev, next;

    Node(int k, int v) { key = k; val = v; }

    }

    private Map map;

    private Node head, tail;

    private int capacity;

    public LRUCache(int capacity) {

    this.capacity = capacity;

    map = new HashMap

    head = new Node(0, 0);

    tail = new Node(0, 0);

    head.next = tail;

    tail.prev = head;

    }

    public int get(int key) {

    if (!map.containsKey(key)) return -1;

    Node node = map.get(key);

    remove(node);

    addToHead(node);

    return node.val;

    }

    public void put(int key, int value) {

    if (map.containsKey(key)) {

    remove(map.get(key));

    }

    Node node = new Node(key, value);

    map.put(key, node);

    addToHead(node);

    if (map.size() > capacity) {

    Node tailNode = tail.prev;

    remove(tailNode);

    map.remove(tailNode.key);

    }

    }

    private void remove(Node node) {

    node.prev.next = node.next;

    node.next.prev = node.prev;

    }

    private void addToHead(Node node) {

    node.next = head.next;

    node.prev = head;

    head.next.prev = node;

    head.next = node;

    }

    }


相关推荐
会飞De琥珀1 小时前
java工具类,字符串转时间
java·开发语言
2501_908329852 小时前
实战:用OpenCV和Python进行人脸识别
jvm·数据库·python
曹牧2 小时前
JSON 数组的正确使用方式
java·服务器·前端
LINgZone22 小时前
深入解析:Cglib与JDK动态代理的实现原理、区别及性能对比
java·开发语言
华科易迅2 小时前
Spring JDBC
java·后端·spring
云烟成雨TD2 小时前
Spring AI 1.x 系列【17】函数型工具开发与使用
java·人工智能·spring
云烟成雨TD3 小时前
Spring AI 1.x 系列【15】AI Agent 基石:Tool Calling 标准与 Spring AI 集成
java·人工智能·spring
咸鱼2.03 小时前
【java入门到放弃】杂记
java·开发语言
亦暖筑序3 小时前
《Spring AI 实战系列 入门篇》第 3 篇
java