算法
常见的基础算法:递归、排序、枚举
时间复杂度
常见的时间复杂度:
- 常数阶:O(1)
- 对数阶:O(logN)
- 线性阶:O(n)
- 线性对数阶:O(nlogN)
- 平方阶:O(n^2)
- 立方阶:O(n^3)
- 指数阶:O(2^N)
复杂度分析技巧:
- 看有几重循环,一重是 O(n),两重是 O(n^2),以此类推
- 如果有二分,则为 O(logN)
- 保留最高项, 去掉常数项
空间复杂度
快速排序
流程:
- 随机选择数组中的一个数 A,以这个数为基准
- 将其他数字跟这个数进行比较,比这个数小的放在其左边,大的放在其右边
- 经过一次循环后,A 的左边都是小于 A 的,右边都是大于 A 的
- 继续将左边和右边的数递归前面的过程
实现代码:
// 比较函数
function compare(a, b) {
if (a === b) {
return 0;
}
return a < b ? -1 : 1;
}
// 原地交换函数
function swap(array, a, b) {
[array[a], array[b]] = [array[b], array[a]];
}
// 划分操作函数
function partition(array, left, right) {
const pivot = array[Math.floor((right + left) / 2)];
let i = left;
let j = right;
while (i <= j) {
while (compare(array[i], pivot) === -1) {
i++;
}
while (compare(array[j], pivot) === 1) {
j--;
}
if (i <= j) {
swap(array, i, j);
i++;
j--;
}
}
return i;
}
function quick(array, left, right) {
let index;
if (array.length > 1) {
index = partition(array, left, right);
if (left < index - 1) {
quick(array, left, index - 1);
}
if (index < right) {
quick(array, index, right);
}
}
return array;
}
function quickSort(array) {
return quick(array, 0, array.length - 1);
}
使用:
const data = [25, 18, 66, 45, 77, 31, 96, 52];
console.log(quickSort(data));
二分查找
二分查找采用分治思想,时间复杂度是 O(logN)
场景:在一堆有序的数中找出指定的数
流程:
- 找到数组中间的数 A,与要找的数比较大小
- 如果 A 较大,则从前半部分查找,否则从后半部分查找
- 不断缩小数量级,每次比较都扔掉一半的数据,直到找完数组为止
题目:在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
function find(target, array) {
let i = 0;
let j = array[i].length - 1;
while (i < array.length && j >= 0) {
if (array[i][j] === target) {
return [i, j];
} else if (array[i][j] > target) {
j--;
} else {
return true;
}
}
return false;
}
const data = [
[1, 2, 3, 4],
[5, 9, 10, 11],
[13, 20, 21, 23]
];
console.log(find(10, data));
冒泡排序
选择排序
插入排序
归并排序
归并排序采用分治思想。将一个数组分成 2 个,再分成 4 个,依次下去,直到分割成一个一个的数据, 再将这些数据两两合并,直到归并成原始数组。
将小数组合并成大数组,先创建一个临时数组 C,比较 A[0],B[0],将较小值放到 C[0],再比较 A[1]与 B[0],将较小值放到 C[1],直到对 A,B 都遍历一遍。
方式一:
function sortArray(nums) {
if (nums.length < 2) return nums;
let middle = Math.floor(nums.length / 2);
let left = [],
right = [];
left = nums.slice(0, middle);
right = nums.slice(middle);
return merge(sortArray(left), sortArray(right));
}
function merge(left, right) {
let result = [];
while (left.length && right.length) {
if (left[0] < right[0]) {
result.push(left.shift());
} else {
result.push(right.shift());
}
}
while (left.length) {
result.push(left.shift());
}
while (right.length) {
result.push(right.shift());
}
return result;
}
let arr = [2, 1, 4, 5, 3, 1, 5, 6, 0];
let res = sortArray(arr);
console.log(res); // [0, 1, 1, 2, 3, 4, 5, 5, 6]
方式二、
function mergeArray(arr, first, mid, last, temp) {
let i = first;
let m = mid;
let j = mid + 1;
let n = last;
let k = 0;
while (i <= m && j <= n) {
if (arr[i] < arr[j]) {
temp[k++] = arr[i++];
} else {
temp[k++] = arr[j++];
}
}
while (i <= m) {
temp[k++] = arr[i++];
}
while (j <= n) {
temp[k++] = arr[j++];
}
for (let l = 0; l < k; l++) {
arr[first + l] = temp[l];
}
return arr;
}
function mergeSort(arr, first, last, temp) {
if (first < last) {
let mid = Math.floor((first + last) / 2);
mergeSort(arr, first, mid, temp); // 左子数组有序
mergeSort(arr, mid + 1, last, temp); // 右子数组有序
arr = mergeArray(arr, first, mid, last, temp);
}
return arr;
}
let arr = [2, 1, 4, 5, 3, 1, 5, 6, 0];
let temp = [];
let SortedArr = mergeSort(arr, 0, arr.length - 1, temp);
console.log(SortedArr); // [0, 1, 1, 2, 3, 4, 5, 5, 6]
数组生成树形结构
const arr = [
{ id: 1, value: '节点1', pid: 0 },
{ id: 2, value: '节点2', pid: 1 },
{ id: 3, value: '节点3', pid: 1 },
{ id: 4, value: '节点4', pid: 2 },
{ id: 5, value: '节点5', pid: 0 },
{ id: 6, value: '节点6', pid: 5 },
{ id: 7, value: '节点7', pid: 6 },
{ id: 8, value: '节点8', pid: 6 }
];
期望结果如下:
[
{
"id": 1,
"value": "节点1",
"pid": 0,
"children": [
{
"id": 2,
"value": "节点2",
"pid": 1,
"children": [
{
"id": 4,
"value": "节点4",
"pid": 2,
"children": []
}
]
},
{
"id": 3,
"value": "节点3",
"pid": 1,
"children": []
}
]
},
{
"id": 5,
"value": "节点5",
"pid": 0,
"children": [
{
"id": 6,
"value": "节点6",
"pid": 5,
"children": [
{
"id": 7,
"value": "节点7",
"pid": 6,
"children": []
},
{
"id": 8,
"value": "节点8",
"pid": 6,
"children": []
}
]
}
]
}
]
方式一、递归实现
function buildTree(arr, pid = 0) {
const tree = [];
for (const item of arr) {
if (item.pid === pid) {
const children = buildTree(arr, item.id);
if (children.length > 0) {
item.children = children;
} else {
item.children = [];
}
tree.push(item);
}
}
return tree;
}