2026-10-9 leetcode100刷题+面经整理

字母异位词分组

一个字符串数组,将 字母异位词 组合在一起。可以按任意顺序返回结果列表。

输入: strs = "eat", "tea", "tan", "ate", "nat", "bat"

输出: \["bat","nat","tan","ate","eat","tea"]

思路:遍历每一个字符串,利用HashMap,先按字字典序生成key,value为当前字符串,最后返回所有values值

语法:s.toCharArray->char\[\] arr Arrays.sort(arr)->有序的char\[\] arr

new String(arr)->得到key

map.computeIfAbsent(key,k->new ArrayList<>()).add(s)->构建Hash

new ArrayList<>(map.values())->提取value值

三数之和

给出一个数组,找出i!=j!=k,i,j,k处和为0的三元组,并返回三元组的集合

思路:排序+固定一个点+L,R双指针

排序之后,相同的数字会挤在一起,"去重"就从"全局判重"变成了"相邻跳过"

核心思路:固定一个 + 两数之和的双指针

1. 整体框架

文本

编辑

复制代码
数组排好序: -4 -1 -1  0  1  2  2  3
              i  L--------------->R
  • 枚举 i(三元组里最小的那个数),范围 [0, n-3];
  • 在 i 右边的区间 [i+1, n) 里,用 L、R 两个指针 找两数之和等于 -nums[i];
  • 因为数组有序:
    • sum < target → 太小,L++(只能往右挪才变大)
    • sum > target → 太大,R--(只能往左挪才变小)
    • sum == target → 命中,记录答案,然后 L++、R-- 继续找

这就是经典的「三数之和 = 排序 + 固定一个 + 两数之和双指针」,把 O(n³) 压到 O(n²)。

2. 去重的三个位置(本题唯一容易写错的地方)

表格

位置 写法 原因
i 去重 if (i > 0 && nums[i] == nums[i-1]) continue; 同一个值作为第一个数,产生的三元组必然重复
L 去重 命中后 while (L < R && nums[L] == nums[L+1]) L++; 避免第二个数重复
R 去重 命中后 while (L < R && nums[R] == nums[R-1]) R--; 避免第三个数重复

⚠️ 关键细节 :去重是「和前一个比」,不是「和后一个比完就停」。 L/R 去重必须在命中之后做 ,做完还要再各挪一步(L++; R--;),否则死循环。

接雨水

思路:每一轮先更新 两边的最高墙,再比较 谁矮------矮的那一侧,它的水位已经被锁死,可以当场结算,一格一格的算,然后累加

1.java的hashmap底层实现?是不是线程安全的?

┌─────────────────────────────────────────────────────────────┐

│ HashMap 底层结构 │

│ │

│ 数组 + 链表 + 红黑树 │

│ │

│ put 流程: │

│ 1. hash 扰动 │

│ 2. 计算索引 (n-1) & hash │

│ 3. 空位直接放,非空遍历链表/红黑树 │

│ 4. 链表长度 ≥ 8 且容量 ≥ 64 → 转红黑树 │

│ 5. size > 阈值 → 扩容(容量翻倍) │

│ │

│ 关键参数: │

│ 容量 16,负载因子 0.75,树化阈值 8,链化阈值 6 │

│ │

└─────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────┐

│ 线程安全性 │

│ │

│ HashMap:❌ 不安全 │

│ ├─ JDK 7:头插法扩容 → 死循环 │

│ └─ JDK 8:尾插法 → 不死循环,但仍丢数据 │

│ │

│ 替代方案: │

│ ├─ Hashtable:全表锁,性能差 │

│ ├─ synchronizedMap:包装锁,一般 │

│ └─ ConcurrentHashMap:CAS + synchronized,高并发首选 │

│ │

└─────────────────────────────────────────────────────────────┘

为什么容量必须的2的幂次方?

在计算数组索引时加快运算,& 比 % 快得多

使分布均匀 ,n - 1 低位全是 1,hash 的每一位都能影响索引

index = hash % capacity == hash & (capacity - 1)

ConcurrentHashMap 的核心

JDK 7:分段锁(Segment)

  • 把整个 map 分成多个 Segment

  • 每个 Segment 独立加锁

  • 不同 Segment 可以并发访问

JDK 8:CAS + synchronized

  • 取消 Segment,直接用 Node 数组

  • 空节点用 CAS 插入

  • 非空节点用 synchronized 锁头节点

  • 锁粒度更细,并发度更高

2.string stringbuilder stringbuffer的区别

┌─────────────────────────────────────────────────────────────┐

│ String(不可变) │

│ │

│ final char\[\] value │

│ 每次修改 → 创建新对象 │

│ 线程安全(因为不可变) │

│ 适合:少量、不常变的字符串 │

│ │

└─────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────┐

│ StringBuilder(可变,不安全) │

│ │

│ char\[\] value(可修改) │

│ 直接改数组,不创建新对象 │

│ 线程不安全(无锁) │

│ 适合:单线程频繁拼接 │

│ 性能:最高 │

│ │

└─────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────┐

│ StringBuffer(可变,安全) │

│ │

│ char\[\] value(可修改) │

│ 所有方法加 synchronized │

│ 线程安全 │

│ 适合:多线程频繁拼接 │

│ 性能:较高(有锁开销) │

│ │

└─────────────────────────────────────────────────────────────┘

String:不可变,线程安全,频繁修改性能差。

StringBuilder:可变,线程不安全,单线程性能最高。

StringBuffer:可变,线程安全,多线程用,有锁开销

3.优化sql的几个角度

开启慢查询日志定位耗时超过阈值(比如1秒)的SQL

首先利用EXPLAIN。 重点看 type 是不是 ALL(全表扫描,索引失效)、key 是不是 NULL(没用索引)

第二步针对性优化:

最高优先是索引优化。 一是设计合理的联合索引;二是尽量用覆盖索引,让查询列都在索引里,避免回表;三是注意刚才说的索引失效场景,别写了索引却用不上。

其次是写法优化。 永远不要 SELECT *,只查需要的列;

再次是利用join替代子查询,同时 确保小表驱动大表。

最后是架构层面。 如果单表优化到极限还不够,才考虑分库分表、读写分离或者加缓存层。

B+ 树的核心优势:数据按索引列有序排列,支持二分查找。

4.分库分表的概念,以及怎么实现

两个维度

维度 含义
分库 把数据分散到多个数据库实例
分表 把一张表拆成多张表

┌─────────────────────────────────────────────────────────────┐

│ 分库分表的四种方式 │

│ │

│ 1. 垂直分库 │

│ 按业务拆分:用户库、订单库、商品库 │

│ │

│ 2. 垂直分表 │

│ 按字段拆分:常用字段一张表,不常用字段另一张表 │

│ │

│ 3. 水平分库 │

│ 同业务数据分散到多个库:order_db1、order_db2 │

│ │

│ 4. 水平分表 │

│ 同业务数据分散到多张表:order_0、order_1、order_2 │

│ │

└─────────────────────────────────────────────────────────────┘

5.jvm的垃圾回收机制是怎么工作的

┌─────────────────────────────────────────────────────────────┐

│ JVM 垃圾回收 │

│ │

│ 1. 回收什么:堆中的垃圾对象 │

│ │

│ 2. 怎么判断:可达性分析(GC Roots) │

│ │

│ 3. 怎么回收: │

│ ├─ 标记-清除(有碎片) │

│ ├─ 复制(无碎片,浪费一半) │

│ └─ 标记-整理(无碎片,移动开销) │

│ │

│ 4. 分代模型: │

│ ├─ 新生代(Eden + S0 + S1)→ 复制算法 → Minor GC │

│ └─ 老年代 → 标记-整理 → Full GC │

│ │

│ 5. 回收器: │

│ ├─ Serial / ParNew / Parallel │

│ ├─ CMS(低延迟) │

│ ├─ G1(可预测停顿) │

│ └─ ZGC(超低延迟) │

│ │

└─────────────────────────────────────────────────────────────┘

6.高并发中如何保证线程安全

使用互斥锁、volatile可见性、线程安全的集合类、原子类、semaphore控制同时访问共享资源的线程数、ThreadLocal线程局部变量等。

相关推荐
yi0111 小时前
DAY24: LeetCode 167:两数之和 II|从暴力枚举到左右双指针
笔记·python·算法·leetcode·二分查找·双指针
木井巳1 小时前
【BFS 解决拓扑排序】课程表
java·算法·leetcode·广度优先·宽度优先·推荐算法·图搜索算法
扶风ff1 小时前
练题簿在线免费刷题:会员线下组卷、Word 试卷与成绩导入,课堂检测更方便
java·开发语言·算法·小程序·word
yi0111 小时前
LeetCode 15:三数之和|排序 + 双指针,如何避免重复答案?
笔记·python·算法·leetcode·双指针
北风toto2 小时前
数据库笔记:Armstrong 公理系统与集合论的深度辨析
数据库·笔记
EasyBr指纹浏览器2 小时前
我的开源项目:小红书笔记归档,把来源和缺项一起留下
笔记·小红书·开源工具·素材管理·内容归档
海海不掉头发2 小时前
图论及其应用_课堂笔记整理_CSDN博客
笔记·图论
-dzk-2 小时前
【多维动态规划】LC 1143.最长公共子序列
算法·动态规划
志尊宝2 小时前
Vue3 零基础每日笔记(075):图片懒加载与骨架屏
javascript·vue.js·笔记