1.冒泡排序
重复走访要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。走访数列的工作是重复地进行直到不用再交换
function bubbleSort(arr) {
for (let i = 0; i < arr.length; i++) {
for (let j = 0; j < arr.length - 1 - i; j++) {
if (arr[j] > arr[j + 1]) {
[arr[j], arr[j + 1]] = [arr[j + 1], arr[j]];
}
//去重
if (arr[j] === arr[j + 1]) {
arr.splice(j, 1);
}
}
}
return arr;
}
2.选择排序
首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕
function selectionSort(arr) {
for (let i = 0; i < arr.length; i++) {
let minIndex = i;
for (let j = i + 1; j < arr.length; j++) {
if (arr[j] < arr[minIndex]) {
minIndex = j;
}
}
[arr[i], arr[minIndex]] = [arr[minIndex], arr[i]];
}
return arr;
}
3.插入排序
它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。插入排序在实现上,通常采用in-place排序(即只需用到O(1)的额外空间的排序),因而在从后向前扫描过程中,需要反复把已排序元素逐步向后挪位,为最新元素提供插入空间
function insertSort(arr) {
let len = arr.length;
for (let i = 1; i < len; i++) {
let temp = arr[i];
let j = i - 1; //默认已排序的元素
while (j >= 0 && arr[j] > temp) {
//在已排序好的队列中从后向前扫描
arr[j + 1] = arr[j]; //已排序的元素大于新元素,将该元素移到一下个位置
j--;
}
arr[j + 1] = temp;
}
return arr;
}
4.快速排序
在数据集之中,选择一个元素作为”基准”(pivot)。所有小于”基准”的元素,都移到”基准”的左边;所有大于”基准”的元素,都移到”基准”的右边。对”基准”左边和右边的两个子集,不断重复第一步和第二步,直到所有子集只剩下一个元素为止
function quickSort(arr) {
if (arr.length <= 1) {
return arr;
}
let pivotIndex = Math.floor(arr.length / 2);
let pivot = arr.splice(pivotIndex, 1)[0];
let left = [];
let right = [];
for (let i = 0; i < arr.length; i++) {
if (arr[i] < pivot) {
left.push(arr[i]);
} else {
right.push(arr[i]);
}
}
return quickSort(left).concat([pivot], quickSort(right));
}
5. 二分查找
假设数组中元素升序排列,将表中间位置数字与查找数字比较,若相等,则查找成功。否则利用中间位置记录将表分成前、后两个子表,如果中间位置记录的数字大于查找数字,则查找前一子表,否则查找后一子表。重复以上过程,直到找到满足条件的记录,则查找成功,或直到子表不存在为止,此时查找不成功
var Arr = [3, 5, 6, 7, 9, 12, 15];
function binary(find, arr, low = 0, high = arr.length - 1) {
if (low <= high) {
let mid = Math.ceil((high + low) / 2);
if (arr[mid] === find) {
return mid;
} else if (arr[mid] > find) {
return binary(find, arr, low, mid - 1);
} else {
return binary(find, arr, mid + 1, high);
}
}
return -1;
}
binary(10, Arr);
6. 杨辉三角
var generate = function(numRows) {
if (numRows) {
var result = [[1]];
for (var i = 1; i < numRows; i++) {
result[i] = [];
for (var j = 0; j < i + 1; j++) {
result[i][j] = (result[i - 1][j] || 0) + (result[i - 1][j - 1] || 0);
}
}
return result;
} else {
return [];
}
};
console.log(generate(5)); // [ [ 1 ], [ 1, 1 ], [ 1, 2, 1 ], [ 1, 3, 3, 1 ], [ 1, 4, 6, 4, 1 ] ]
console.log(generate(5)[4]); // [ 1, 4, 6, 4, 1 ]
7. 约瑟夫环问题
- 解法1。 使用链表 循环链表的解题思路比较简单,只需要将问题描述转换成代码即可。房间中的N个人组成一个长度为N的链表,首尾相接组成循环链表。列表中的每一项的值即为每个人的编号,在数到M时将该项(记为x)剔除,即该项的前一项的next不再指向x,而是x.next。依此规律遍历链表,直至链表中只剩下一项。
function createList(num) {
//链表节点的数据结构
function createNode(value) {
return {
value: value,
next: ''
}
}
//链表头节点
let head = createNode(1);
let node = head;
//自头节点之后创建节点之间的关联关系
for (let i = 2; i <= num; i++) {
node.next = createNode(i);
node = node.next;
}
//最后一个节点指向头节点,构成循环链表
node.next = head;
return head;
}
function deleteListNode(num, nth) {
//创建数据长度为num的循环链表
let node = createList(num);
//链表长度>1时,继续下一轮
while (num > 1) {
for (let i = 1; i <= nth - 1; i++) {
if (i == nth - 1) {
//i为nth-1,则node.next即为第nth个节点。剔除node.next
node.next = node.next.next;
//链表长度--
num--;
}
node = node.next;
}
}
//剩余的最后一个节点的value值即为最后一人编号
return node.value
}
deleteListNode(6, 4)
- 解法2: 使用递归
function JosephusR(num, nth) {
let value = 0;
for (let i = 1; i <= num; i++) {
//此处为对i取余,上述递归中num也是在逐渐变小的,所以此处为i而非num
value = (value + nth) % i;
}
return value + 1;
}
JosephusR(6, 4)
参考链接: www.jb51.net/article/222…
8. 最优方法 判断是否是质数
定义: 质数又称素数。一个大于1的自然数,除了1和它自身外,不能被其他自然数整除的数叫做质数;否则称为合数(规定1既不是质数也不是合数)
// 最优方法 封装函数判断质数
export function isPrime(num) {
// 1. 获取num的平凡根
const temp = parseInt(Math.sqrt(num))
// 2. 循环判断
for (let i = 2; i <= temp; i++) {
if (num % i === 0) {
return false
}
}
return true
}