时间复杂度
- O(1):无论多少数据,都不会影响操作时间。例如读取对象属性。
- O(n):随着数据的增加复杂度线性增长。比如获取一堆数中最大的的值,需要遍历一边所有数据,数据越多速度越慢。
- O(n²):例如排序算法中的冒泡,把上面的O(n)行为重复n次。找到最大数,取出。在剩下那堆里继续找最大数。
- O(logn):二分法,从排好序的数中找某一特定数。
交换函数
const swap = (nums, i, j) => {
let temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
return nums;
};
选择排序
描述
- 选择所有数中最小的排到第一位
- 从第二位开始选择剩余最小排到第二位,重复
冒泡排序
描述
- 从第一个数开始比较相邻的两个数的大小
- 重复交换直到最后一个数
- 此时最后一个数即为最值,下次交换区间为第一个数至倒数第二个数
- 时间O(n²),空间O(1)
- 通过添加一个标识,如果本次未进行任何交换,那这个数组已经排好序了。直接返回结果
code
const bubbleSort = nums => {
if (nums.length <= 1) return nums;
let flag = false;
for (let i = 0; i < nums.length; i++) {
for (let j = 0; j < nums.length - i - 1; j++) {
if (nums[j] > nums[j + 1]) {
swap(nums, j, j + 1);
flag = true;
}
}
if (!flag) {
return nums;
} else {
flag = false;
}
}
return nums;
};
插入排序
描述
- 默认第一位数是一个已排好序的数组A
- 将第二位数,由数组A从后向前比较,将其插入在遇到第一个比他小的数后面
code
const insertSort = nums => {
if (nums.length <= 1) return nums;
let len = nums.length;
let curr, pre;
for (let i = 1; i < len; i++) {
pre = i - 1;
curr = nums[i];
while (pre >= 0 && nums[pre] > curr) {
nums[pre + 1] = nums[pre];
pre--;
}
nums[pre + 1] = curr;
}
return nums;
};
希尔算法
描述
- 希尔算法是插入算法的一种优化
- 设置一个增量gap,例如[3,9,7,5],gap可以首先设置为2。将数组分为[3,7]和[5,9]进行排序。
- 第一次排序后数组为[3,5,7,9],然后把增量再除2设置为1。
- 当增量为1时作为一个排序来处理。
- 希尔排序的核心在增量的设置。
code
const shellSort = nums => {
let len = nums.length;
for (let gap = Math.floor(len / 2); gap > 0; gap = Math.floor(gap / 2)) {
for (let i = gap; i < len; i++) {
let j = i;
let curr = nums[i];
while (j - gap >= 0 && curr < nums[j - gap]) {
nums[j] = nums[j - gap];
j = j - gap;
}
nums[j] = curr;
}
}
return nums;
};
归并排序
描述
- 一个有序序列可以由两个有序子序列组成。先将一个序列分为两个子序列,进行归并排序。
- 将问题转化为对两个已排序子序列进行排序。
- 递归结束条件为子序列长度为1
- merge时需要开辟新空间
code
const mergeSort = nums => {
if (nums.length <= 1) return nums;
let m = Math.floor(nums.length / 2);
let l = nums.slice(0, m);
let r = nums.slice(m);
return merge(mergeSort(l), mergeSort(r));
};
const merge = (left, right) => {
let res = [];
while (left.length > 0 && right.length > 0) {
left[0] < right[0] ? res.push(left.shift()) : res.push(right.shift());
}
if (left.length > 0 || right.length > 0) {
return res.concat(left, right);
}
return res;
};
快排
描述
- 选择一个基准点,把数列中小于基准点的放在左边,大于的放在右边
- 递归上述过程直到子序列长度为1
code
const quickSort = nums => {
if (nums.length <= 1) return nums;
let pivotIndex = Math.floor(nums.length / 2);
let pivot = nums.splice(pivotIndex, 1)[0];
let l = [];
let r = [];
for (let i = 0; i < nums.length; i++) {
nums[i] < pivot ? l.push(nums[i]) : r.push(nums[i]);
}
return quickSort(l).concat([pivot], quickSort(r));
};