🥳前端算法面试--贪心算法求解多区间--说句题外话

648 阅读4分钟

今天分享的内容是如何用贪心算法,在固定范围内找到更多子区间

问题描述

现在有多个子区间,区间的范围是从 n 到 m,请在这些区间中,找出最多不相互覆盖的子区间

const data = [
	[6, 8],
	[2, 4],
	[3, 5],
	[1, 5],
	[5, 9],
	[8, 10],
];

data 是一个二维数组,其中可以找到的最多,不冲突的子区间是:

const spaces = [ [ 2, 4 ], [ 6, 8 ], [ 8, 10 ] ];

思路分析

寻找最多区间的问题,就要请出我们今天的主角了--贪心算法

贪心算法是一种在许多情况下都可以有效解决问题的算法。它的基本思想是每次选择当前最优的解,即局部最优解。贪心算法的求解过程是每次选择当前最优的解,直到满足终止条件。

贪心顾名思义,就是只顾眼前的利益,只顾着眼前能看见的最优。虽然不好听,但是解决当前的问题却再合适不过了。

对于当前的问题,可以先将各个区间按照左端点排序,然后找下一个区间,要求和当前区间不相互覆盖,并且区间范围最小。为什么?因为这样可以使剩下的空白区间范围足够大,可以容纳更多的子区间。优先最短,构成局部最优,这就是贪心思想。

说是这么说,看起来挺简单的,但是按照上面的描述来写代码却不容易。可以换个思路:

对区间的右端点进行升序排序,每加入一个线段,然后选择后面一个或者多个右端点相同的区间,然后在选中区间内选择左端点最大的那一条,也就是区间最小的。如果加入以后不会跟之前的区间不会相互覆盖,那么就加入,否则就继续判断后面的区间

很简单吧,来看看代码咋写

代码实现

//倒序插入
const insertOrder = (array, value) => {
	for (let i = 0; i < array.length; i++) {
		if (value[0] >= array[i][0]) {
			array[i].splice(i, 0, value);
			return;
		}
	}
	array.push(value);
};

// 找到最多的区间
// table是区间表
const findManySpace = (table) => {
	table = table.sort((a, b) => a[1] - b[1]);

	const res = [];
	for (let i = 0; i < table.length; i++) {
		let tempArray = [];
		let j = i;
		// 找到相同右端点的区间
		for (; j < table.length; j++) {
			// 倒序插入
			if (table[i][1] == table[j][1]) insertOrder(tempArray, table[j]);
			else break;
		}
		i = j - 1;

		// res初始可能为空,就不考虑区间覆盖的问题
		if (res.length == 0) {
			res.push(tempArray[0]);
			continue;
		}

		// 遍历,找到第一个不覆盖的区间
		for (let i = 0; i < tempArray.length; i++) {
			if (tempArray[i][0] >= res[res.length - 1][1]) {
				res.push(tempArray[i]);
				break;
			}
		}
	}

	console.log(res);
};

代码的思路,也就入上面描述中所讲的一样,代码就不做详细解释了。

其中有两个需要注意的地方,提一下

  1. 为了能够快速地在相同右端点的区间中,找到最大左端点的区间,可以采用有序插入的方式,这样就不用再对 tempArray 排序了
  2. 在找到若干个相同右端点的区间后,需要修改 i 的值,表示 i 前面的区间已经被考虑过了。下一轮循环直接从 i 后面的区间开始

测试代码

findManySpace(data);
// [ [ 2, 4 ], [ 6, 8 ], [ 8, 10 ] ]

image.png

输出正确

总结

本篇文章分享的是一道非常经典的区间求解问题,主要采用的策略是贪心算法。思路很简单,代码也很简单,难的是,如果不看答案之前,这道题根本做不出来....我在说我自己

说句题外话,写完这篇文章,我已经在算法和数据结构专题上分享了 50 余篇文章了,感觉仍在基础打转。数据结构是基础不假,但会了数据结构绝对不代表会算法,算法是解题方法,像数学题目一样,知识是知识,题目是题目,学会了知识,不代表会做题目。而且题目的解法,技巧是另一个层面的东西。

到现在,本专栏分享的数据结构涵盖了大学本科要求的所有数据,从数组,链表,到二叉树,二叉搜索树,多叉树,AVL 平衡树,B 树,(红黑树暂时没有), 图,集合,堆,hash表,分享的算法有排序算法,贪心算法,回溯算法,动态规划,对于浩如烟海的算法问题,这点很不够看。

刚去力扣试了试身手,结果被杀得卸甲归田...我还是在说我自己

难道要进入做一道会一道,不做就不会的怪圈么...给自己打了一个问号❓

题外话说完了,日更专栏就到这里吧,之后内容改成不定期更新。

有问题可以评论区留言哦。我每天都会分享一篇算法小练习,喜欢就点赞+关注吧