0
点赞
收藏
分享

微信扫一扫

【算法系列】高级篇——1,必会的十大算法

文章目录

1,二分查找(非递归)

在有序数组中查找特定的值。
代码比较死。

升序的版本:

function search(arr, target) {
	let left = 0
	let right = arr.length - 1
	while (left <= right) {
		let middle = Math.floor((left + right) / 2)
		if (arr[middle] === target) {
			return middle
		} else if (arr[middle] > target) {
			right = middle - 1
		} else {
			left = middle + 1
		}
	}
	return -1
}
console.log(search([1, 2, 3, 4, 5, 6, 7], 7))

2,分治思想

把复杂的问题拆解成多个子问题。
步骤为:

  1. 分解。
  2. 解决。
  3. 合并。
    在这里插入图片描述

汉诺塔问题的解:
有三个位置:原位置,中间盘,目标盘。

  1. 将N个盘划分为N-1个盘和1个盘。
  2. N-1个盘递归地移动到中间盘。
  3. 1个盘直接移动到目标盘。
  4. N-1个盘递归地移动到目标盘。
//统计步数
let count = 0
//三个数组
let A = [5, 4, 3, 2, 1]
let B = []
let C = []
//打印状态
function printInfo() {
	console.log("A:" + A)
	console.log("B:" + B)
	console.log("C:" + C)
	console.log("=============================" + (++count))
}
//调用
han(A.length, A, C, B)
function han(n, from, to, middle) {
	//最上面的一个,直接push,pop,打印状态
	if (n === 1) {
		to.push(from.pop())
		printInfo()
		//下面的N个,三步走
	} else {
		han(n - 1, from, middle, to)
		han(1, from, to, middle)
		han(n - 1, middle, to, from)
	}
}

3,动态规划

排列组合,求最优解。
同样是拆分问题,它的子问题互相关联。后面依赖前面。

在这里插入图片描述

背包问题的解:
填表,种类逐渐增加,重量逐渐增加。

0磅:无法放东西。
0种物品:无东西可放。
只有吉他:都是吉他
吉他+音响:123是吉他,4是音响
吉他+音响+电脑:12是上一层的值,3是电脑,4是上一层的值与(当前+以前层)的较大者。
在这里插入图片描述

4,KMP算法(字符串查找算法)

在字符串A中匹配子串B。

暴力匹配:不匹配就回溯。

let a = "123456789344566777"
let b = "344566"
function search(source, target) {
	let i = 0
	let j = 0
	//遍历
	while (i < source.length) {
		if (j > target.length - 1) {
			return i - j + 1
		}
		if (source[i] !== target[j]) {
			i = i - j + 1
			j = 0
		} else {
			i++
			j++
		}
	}
	return -1
}
console.log(search(a, b))

KMP:
如果要匹配ABCD,回溯了,不需要从B位置处开始和A匹配。
而是从D后面直接开始。
如果要匹配ABCDAB,回溯了,那就从后面的A处开始匹配。
在这里插入图片描述
一种实现:

// 主串
let str1 = 'BBC ABCDAB ABCDABCDABDEDC';
// 模式串
let str2 = 'ABCDABD';

let getPMT = (str = '') => {
	if (str.length === 0) return [];
	let pmt = [0];
	let k = 2;
	while (k <= str.length) {
		let temp = str.substring(0, k);
		let length = temp.length;
		// 前缀
		let prefix = temp.substring(0, length - 1).split('').map((item, index) => {
			return temp.substring(0, index + 1);
		});
		// 后缀
		let suffix = temp.substring(1).split('').map((item, index) => {
			return temp.substring(index + 1);
		});
		let publicLength = 0;
		// 比较前缀后缀得出最长公共字符长度
		prefix.forEach(preitem => {
			suffix.forEach(sufitem => {
				if (preitem === sufitem) {
					publicLength = preitem.length > publicLength ? preitem.length : publicLength;
				}
			})
		})
		pmt.push(publicLength);
		k++;
	}
	return pmt;
}
let pmt = getPMT(str2);
let m = 0;
let n = 0;
while (m < str1.length && n < str2.length) {
	if (str1[m] === str2[n]) { // 匹配时,继续比较下一个字符
		n++;
		m++;
	} else if (n > 0) { // 当前不匹配时,如果前面已匹配字符数 > 0,模式串索引往前移动pmt[n - 1]位
		n = pmt[n - 1];
	} else {
		m++;
	}
}
if (n === str2.length) {
	console.log(`str1包含str2,索引位置为${m - str2.length}${m - 1}`);
} else {
	console.log('str1不包含str2');
}

5,贪心算法

排列组合,求最优解。
每次都选一个最优解,直到解决问题。
在这里插入图片描述
先挑选覆盖数量多的,K1,
重新计算覆盖数量。取最大的,K2。
K3。
k5。
此时已经全覆盖了,不再挑选。

6,普里姆算法(最小生成树)

最优解(待补充)

7,克鲁斯卡尔算法(最小生成树)

最优解(待补充)

8,迪杰斯特拉算法(最短路径)

最优解(待补充)

9,弗洛伊德算法(最短路径)

最优解(待补充)

10,马踏棋盘算法(骑士周游)

全经历(待补充)

举报

相关推荐

0 条评论