Java面试之常用的排序算法及其复杂度分析
发布时间 - 2026-01-06 00:00:00 点击率:次冒泡排序因逻辑直观、易暴露边界漏洞而常被面试考察,时间复杂度恒为O(n²),空间复杂度O(1);关键优化是添加swapped标志实现提前终止,使最好情况达O(n)。
冒泡排序为什么在面试里总被问,但实际几乎不用
因为它的逻辑最直观,适合考察对「
比较-交换」过程的理解,也容易暴露边界处理漏洞。时间复杂度固定是 O(n²),无论最好、最坏、平均情况;空间复杂度是 O(1)(原地排序)。面试手写时,常被忽略的点是提前终止优化——如果某轮没发生任何交换,说明已有序,应直接退出。
public static void bubbleSort(int[] arr) {
int n = arr.length;
for (int i = 0; i < n - 1; i++) {
boolean swapped = false;
for (int j = 0; j < n - 1 - i; j++) {
if (arr[j] > arr[j + 1]) {
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
swapped = true;
}
}
if (!swapped) break; // 关键优化,否则无法达到最好情况 O(n)
}
}- 测试用例务必包含已排序数组,验证
swapped优化是否生效 - 注意内层循环上界是
n - 1 - i,不是n - i,否则可能越界 - Java 中传入的是数组引用,无需返回值,但需明确说明这是原地修改
快速排序的 partition 实现有哪两种主流写法
面试高频考点:lomuto 和 hoare 分区方案。前者以最后一个元素为 pivot,代码简洁但对重复元素不友好;后者用首尾双指针,效率略高且天然更稳定(相同元素分布更均匀),但边界条件易错。两者平均时间复杂度都是 O(n log n),最坏退化到 O(n²)(如已排序数组选端点作 pivot),必须强调随机化 pivot 或三数取中来缓解。
// Lomuto 风格(推荐面试写,逻辑清晰)
private static int partition(int[] arr, int low, int high) {
int pivot = arr[high]; // 取末尾为 pivot
int i = low - 1; // i 指向小于 pivot 的右边界
for (int j = low; j < high; j++) {
if (arr[j] <= pivot) {
i++;
swap(arr, i, j);
}
}
swap(arr, i + 1, high);
return i + 1;
}-
hoare版本中,两个指针从两端向中间走,首次相遇位置不一定是 pivot 最终位置,需额外判断 - 递归调用时,
lomuto的左右区间是[low, pi-1]和[pi+1, high];hoare是[low, pi]和[pi+1, high],容易混淆 - Java 8 的
Arrays.sort(int[])对基本类型用的是双轴快排(Dual-Pivot Quicksort),不是单 pivot,这点可作为延伸加分项
归并排序如何体现“稳定”和“非原地”的本质特征
稳定性意味着相等元素的相对顺序不变,归并排序天然满足——合并时若 left[i] == right[j],优先取 left[i] 即可。但它需要额外 O(n) 空间存临时数组,不是原地算法。时间复杂度严格是 O(n log n),不受输入数据影响,适合对最坏性能有要求的场景(比如实时系统)。
private static void mergeSort(int[] arr, int[] temp, int left, int right) {
if (left >= right) return;
int mid = left + (right - left) / 2;
mergeSort(arr, temp, left, mid);
mergeSort(arr, temp, mid + 1, right);
merge(arr, temp, left, mid, right);
}
private static void merge(int[] arr, int[] temp, int left, int mid, int right) {
System.arraycopy(arr, left, temp, left, right - left + 1);
int i = left, j = mid + 1, k = left;
while (i <= mid && j <= right) {
if (temp[i] <= temp[j]) { // 注意这里是 <=,保证稳定性
arr[k++] = temp[i++];
} else {
arr[k++] = temp[j++];
}
}
while (i <= mid) arr[k++] = temp[i++];
while (j <= right) arr[k++] = temp[j++];
}
- 面试手写常漏掉
System.arraycopy这一步,直接在原数组上合并会导致数据覆盖 - 递归入口需传入辅助数组
temp,避免每层都 new,否则空间复杂度变成O(n log n) - 堆排序虽也是
O(n log n),但不稳定,且实际性能通常不如优化后的快排或归并
堆排序建堆过程为何是 O(n),而不是直觉上的 O(n log n)
关键在自底向上调整(siftDown)的代价分析:叶子节点不用调整;倒数第二层最多下沉 1 层;倒数第三层最多下沉 2 层……数学推导可得总操作数上限是 2n。而如果用 n 次 insert(即自顶向下 siftUp),才是 O(n log n)。Java 中没有内置二叉堆类支持索引访问,手写时要注意数组下标从 0 开始时,左子节点是 2*i + 1,不是 2*i。
- 建堆后,每次取出最大值(
arr[0])与末尾交换,再对剩余部分siftDown(0),共n-1次,每次O(log n) - 堆排序是原地的,但不稳定——相同元素在下沉过程中可能跨过彼此改变顺序
- 面试若被问“什么时候选堆排序”,答:内存受限 + 要求最坏
O(n log n)+ 不关心稳定性(如 Top-K 问题)
实际编码中,除非特定约束,否则直接用 Arrays.sort()。手写排序算法的价值不在替代它,而在暴露你对数据移动、比较次数、内存访问模式的直觉——这些细节,往往比背下复杂度公式更重要。
# java
# 编码
# app
# 排序算法
# 冒泡排序
# 为什么
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
EditPlus中的正则表达式 实战(4)
惠州网站建设制作推广,惠州市华视达文化传媒有限公司怎么样?
Midjourney怎么调整光影效果_Midjourney光影调整方法【指南】
EditPlus中的正则表达式 实战(1)
深圳网站制作培训,深圳哪些招聘网站比较好?
如何在阿里云ECS服务器部署织梦CMS网站?
如何确保FTP站点访问权限与数据传输安全?
如何快速搭建安全的FTP站点?
Laravel如何配置任务调度?(Cron Job示例)
太平洋网站制作公司,网络用语太平洋是什么意思?
Android使用GridView实现日历的简单功能
Laravel如何使用Guzzle调用外部接口_Laravel发起HTTP请求与JSON数据解析【详解】
如何在不使用负向后查找的情况下匹配特定条件前的换行符
Mybatis 中的insertOrUpdate操作
如何在腾讯云服务器快速搭建个人网站?
BootStrap整体框架之基础布局组件
Claude怎样写结构化提示词_Claude结构化提示词写法【教程】
深圳网站制作平台,深圳市做网站好的公司有哪些?
laravel怎么配置Redis作为缓存驱动_laravel Redis缓存配置教程
Laravel如何设置自定义的日志文件名_Laravel根据日期或用户ID生成动态日志【技巧】
西安市网站制作公司,哪个相亲网站比较好?西安比较好的相亲网站?
如何在IIS中新建站点并解决端口绑定冲突?
如何在搬瓦工VPS快速搭建网站?
Win11怎么设置虚拟桌面 Win11新建多桌面切换操作【技巧】
Laravel如何生成API文档?(Swagger/OpenAPI教程)
Laravel如何与Docker(Sail)协同开发?(环境搭建教程)
PHP怎么接收前端传的文件路径_处理文件路径参数接收方法【汇总】
如何用腾讯建站主机快速创建免费网站?
Laravel控制器是什么_Laravel MVC架构中Controller的作用与实践
Laravel如何使用查询构建器?(Query Builder高级用法)
php打包exe后无法访问网络共享_共享权限设置方法【教程】
如何生成腾讯云建站专用兑换码?
香港服务器网站卡顿?如何解决网络延迟与负载问题?
Laravel如何处理异常和错误?(Handler示例)
HTML5段落标签p和br怎么选_文本排版常用标签对比【解答】
Win10如何卸载预装Edge扩展_Win10卸载Edge扩展教程【方法】
如何正确下载安装西数主机建站助手?
动图在线制作网站有哪些,滑动动图图集怎么做?
如何在IIS服务器上快速部署高效网站?
Laravel如何实现全文搜索功能?(Scout和Algolia示例)
Swift开发中switch语句值绑定模式
如何快速辨别茅台真假?关键步骤解析
Laravel如何实现登录错误次数限制_Laravel自带LoginThrottles限流配置【方法】
如何获取免费开源的自助建站系统源码?
长沙企业网站制作哪家好,长沙水业集团官方网站?
高防网站服务器:DDoS防御与BGP线路的AI智能防护方案
Laravel如何与Pusher实现实时通信?(WebSocket示例)
如何在阿里云购买域名并搭建网站?
如何解决hover在ie6中的兼容性问题
javascript如何操作浏览器历史记录_怎样实现无刷新导航

