算法-常见算法
总览
一般常用常考的类型主要有:
- 链表
- 快排
- 二分查找
- 动态规划
- 双指针
- 滑动窗口
- 二叉树
如果要应对前端面试,建议刷:
查找
二分查找
var search = function (nums, target) {
let low = 0,
high = nums.length - 1;
while (low <= high) {
const mid = Math.floor((high - low) / 2) + low;
const num = nums[mid];
if (num === target) {
return mid;
} else if (num > target) {
high = mid - 1;
} else {
low = mid + 1;
}
}
return -1;
};
排序
冒泡排序
/**
* 冒泡排序
* 简介: 就像泡泡一样,每轮中待排序的最大的数字会冒泡到待排序数组的最右边,作为已排序数组;
* https://upload.wikimedia.org/wikipedia/commons/3/37/Bubble_sort_animation.gif
* @param {Array} 需要排序的数组
* @return {Array}
*/
// 时间复杂度 O(n^2): (1+n-1)*(n-1)/2
const bubbleSort = (arr) => {
for (let i = 0; i < arr.length - 1; i++) {
// 是有序的(没交换过,说明已经有序了,这轮结束不需要再比较了)
let isOrder = true;
for (let j = 0; j < arr.length - 1 - i; j++) {
if (arr[j] > arr[j + 1]) {
let t = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = t;
isOrder = false;
}
}
console.log(`第${i + 1}轮的数组结果:`, arr);
if (isOrder) {
console.log("已经有序,提前结束");
break;
}
}
return arr;
};
// bubbleSort([5,4,3,2,1]) => 输出: [1,2,3,4,5]
// bubbleSort([5,3,1,2,4]) => 输出: [1,2,3,4,5]
选择排序
/**
* 选择排序
* 方案: 每轮从待排序数组中的选取出最小的数字,与待排序的最左数字交换位置
* https://pic3.zhimg.com/v2-495e1e8dbe7966a904985c4186a295de_b.webp
* @param {Array} 需要排序的数组
* @return {Array}
*/
// 时间复杂度 O(n^2)
const selectSort = (arr) => {
for (let i = 1; i < arr.length; i++) {
// 最小的数的索引
let minIndex = i - 1;
for (let j = i; j < arr.length; j++) {
if (arr[j] < arr[minIndex]) {
minIndex = j;
}
}
// 交换
if (i - 1 !== minIndex) {
let t = arr[i - 1];
arr[i - 1] = arr[minIndex];
arr[minIndex] = t;
}
console.log(`第${i}轮结果`, arr);
}
return arr;
};
// selectSort([5,4,3,2,1]) => 输出: [1,2,3,4,5]
// selectSort([5,3,1,2,4]) => 输出: [1,2,3,4,5]
链表
链表-裁剪节点
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} node
* @return {void} Do not return anything, modify node in-place instead.
*/
a = { val: 3, next: null };
b = { val: 3121, next: a };
c = { val: 876, next: b };
d = { val: 312, next: c };
// d => c => b => a 删除后: d => b => a
var deleteNode = function (node) {
node.val = node.next.val;
node.next = node.next.next;
};
链表-打印链表
a = { val: 3, next: null };
b = { val: 3121, next: a };
c = { val: 876, next: b };
// 输入一个链表,按链表值从尾到头的顺序返回一个ArrayList。
const printListFromTail2Head = (linkedList) => {
const arr = [linkedList.val];
let cur = linkedList;
while (cur.next) {
cur = cur.next;
arr.unshift(cur.val);
}
return arr;
};
链表-反转链表
a = { val: 3, next: null };
b = { val: 3121, next: a };
c = { val: 876, next: b };
d = { val: 312, next: c };
// 原来 d => c => b => a ; 反转后 a => b => c => d
// c. d b a
// b. c d a
// a. b c d
// 第一轮之后: currentNode: c head: d headNode: c
const reverseLinkedList = (head) => {
if (!head.next) {
return head;
}
let cur = null;
let headNode = head;
// 将基准点的下一项移动到头部的第一项
while (head && head.next) {
cur = head.next;
head.next = cur.next;
cur.next = headNode;
headNode = cur;
}
return headNode;
};
相关链接
-
十大经典排序算法
-
原地算法
-
数据结构和算法(三):冒泡、选择、插入排序算法
Tags: