一、前端为什么学算法
下面直接给出让人无法反驳的一些理由
- 各种大厂面试硬性要求面试算法
- 精通算法能更好的阅读一些框架的源码,比如react、vue中的diff计算
- 算法能使你的思想更加灵活
- 你是否想做一辈子的增删改查
二、冒泡、插入、选择
冒泡排序
- 概念:冒泡排序只会操作相邻的两个数据。每次冒泡操作都会对相邻的两个元素进行比较,看是否满足大小关系要求。如果不满足就让它俩互换。一次冒泡会让至少一个元素移动到它应该在的位置,重复 n 次,就完成了 n 个数据的排序工作。
- 时间复杂度 O(n2)
- 空间复杂度 O(1)
- 代码实现(从小到大),两层for循环,第一层表示冒泡次数,第二层对比相邻元素,第二次遍历需要注意的是已经冒泡过的元素不在需要遍历
function bubbleSort(target) {
if (!target || !target instanceof Array || target.length < 2) {
return target || []
}
let len = target.length
// 遍历len次,即经过len次冒泡
for (let i=0; i<len; i++) {
let isDone = false
// j < len- i - 1是因为len - i -1及之后的肯定比之前的都大
for(let j=0; j<len - i - 1; j ++) {
if (target[j] < target[j + 1]) {
// 每次循环把此次中最大的移到相应的位置,交换位置
let tem = target[j]
target[j] = target[j + 1]
target[j + 1] = tem
isDone = true
}
}
// 如果此次循环没有交换位置,则表示已经排序结束
if (!isDone) break
}
}
插入排序
- 概念:将数组分为有空间和无序空间,有序空间初始值为数组第一项,取出无序空间一项,插入到有序空间中合适的位置,循环n遍,就可以得到一个有序数组
- 时间复杂度O(n2)
- 空间复杂度O(1)
- 代码实现(从小到大),两层for循环,第一次遍历无序空间,第二层遍历有序空间,将元素插入合适的位置(包含移动和插入)
function insertSort(target) {
if (!target || !target instanceof Array || target.length < 2) {
return target || []
}
let len = target.length
// 遍历无序空间
for(let i=1; i<len; i++) {
let value = target[i]
let j = i - 1
for(; j>=0; --j) {
// 第二次循环遍历有序空间
if(target[j] > value) {
// 如果value < target[j],将target[j]后移一位
target[j + 1] = target[j]
} else break
}
target[j + 1] = value // 插入数据
}
return target
}
选择排序
- 概念:选择排序算法的实现思路有点类似插入排序,也分有序空间和无序空间。但是选择排序每次会从无序空间中找到最小的元素,将其放到有序空间的末尾,即找到最小元素和i元素交换位置。
- 时间复杂度 O(n2)
- 空间复杂度 O(1)
- 代码实现(从小到大),两层for循环,第一层遍历所有元素,交换位置,第二层,找出最小元素
function selectSort(target) {
if (!target || !target instanceof Array || target.length < 2) {
return target || []
}
for(let i=0; i<target.length; i++){
let minIndex = i
// 循环找出最小元素
for(let j=i+1; j<target.length; j++){
if(target[j] < target[minIndex]){
minIndex = j
}
}
let tem = target[i]
target[i] = target[minIndex]
target[minIndex] = tem
}
return target
}