写一个方法实现“交换排序算法”,并解释下时间复杂度和空间复杂度
/**
* 交换排序(冒泡排序)
*
* @param {Array<number>} arr 待排序的数组
* @returns {Array<number>} 排序后的数组
*/
function exchangeSort(arr) {
const n = arr.length;
let swapped; // 优化:如果一趟没有交换,说明已经有序
for (let i = 0; i < n - 1; i++) {
swapped = false; // 每趟开始前重置 swapped
for (let j = 0; j < n - 1 - i; j++) {
if (arr[j] > arr[j + 1]) {
// 交换元素
[arr[j], arr[j + 1]] = [arr[j + 1], arr[j]]; // ES6 解构赋值
swapped = true;
}
}
if (!swapped) {
// 如果没有交换,说明已经有序,提前退出
break;
}
}
return arr;
}
// 示例用法:
const unsortedArray = [5, 2, 9, 1, 5, 6];
const sortedArray = exchangeSort(unsortedArray);
console.log(sortedArray); // 输出: [1, 2, 5, 5, 6, 9]
/**
* 时间复杂度和空间复杂度分析:
*
* 时间复杂度:
* - 最好情况:O(n) 当输入数组已经排好序时,只需遍历一次,没有交换操作。因为添加了 swapped 标记,一趟下来没有交换就提前退出。
* - 平均情况:O(n^2) 需要遍历 n-1 趟,每趟平均比较 n/2 次。
* - 最坏情况:O(n^2) 当输入数组是逆序时,需要进行最多的比较和交换操作。
*
* 空间复杂度:O(1) 算法只使用了常数个额外变量(n, swapped, i, j),与输入数组的大小无关,因此空间复杂度为常数级别。
* 属于原地排序算法。
*/
代码解释:
exchangeSort(arr)
函数: 接收一个数字数组arr
作为输入。- 外层循环
for (let i = 0; i < n - 1; i++)
: 控制排序的趟数,一共需要 n-1 趟。 swapped
标记: 用于优化,如果一趟循环中没有发生交换,说明数组已经有序,可以提前结束排序。- 内层循环
for (let j = 0; j < n - 1 - i; j++)
: 在每一趟中,比较相邻元素并交换它们的位置,使得最大的元素“冒泡”到数组的末尾。 每一趟过后,最大的元素都会被放到正确的位置,因此内层循环的范围逐渐减小。 [arr[j], arr[j + 1]] = [arr[j + 1], arr[j]];
: 使用 ES6 解构赋值简洁地交换两个元素的值。if (!swapped)
: 检查是否进行了交换,如果没有,说明数组已经有序,提前退出循环。return arr;
: 返回排序后的数组。
关键点:
- 冒泡排序: 交换排序也称为冒泡排序,因为它像气泡一样,较大的元素会逐渐“冒泡”到数组的末尾。
- 原地排序: 冒泡排序是原地排序算法,因为它直接在原始数组上进行操作,不需要额外的空间来存储数组的副本。
- 稳定性: 冒泡排序是稳定的排序算法,这意味着如果数组中存在相等的元素,它们的相对顺序在排序后不会改变。
这个改进的版本通过 swapped
标记进行优化,在最好情况下(数组已经有序)时间复杂度可以达到 O(n)。 这使得它在处理部分有序的数组时效率更高.
希望这个解释能够帮助你理解交换排序算法(冒泡排序)的实现、时间复杂度和空间复杂度。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了