今天分享的内容是如何用贪心算法,在固定范围内找到更多子区间
问题描述
现在有多个子区间,区间的范围是从 n 到 m,请在这些区间中,找出最多不相互覆盖的子区间
javascript
const data = [
[6, 8],
[2, 4],
[3, 5],
[1, 5],
[5, 9],
[8, 10],
];
data 是一个二维数组,其中可以找到的最多,不冲突的子区间是:
javascript
const spaces = [ [ 2, 4 ], [ 6, 8 ], [ 8, 10 ] ];
思路分析
寻找最多区间的问题,就要请出我们今天的主角了--贪心算法
贪心算法是一种在许多情况下都可以有效解决问题的算法。它的基本思想是每次选择当前最优的解,即局部最优解。贪心算法的求解过程是每次选择当前最优的解,直到满足终止条件。
贪心顾名思义,就是只顾眼前的利益,只顾着眼前能看见的最优。虽然不好听,但是解决当前的问题却再合适不过了。
对于当前的问题,可以先将各个区间按照左端点排序,然后找下一个区间,要求和当前区间不相互覆盖,并且区间范围最小。为什么?因为这样可以使剩下的空白区间范围足够大,可以容纳更多的子区间。优先最短,构成局部最优,这就是贪心思想。
说是这么说,看起来挺简单的,但是按照上面的描述来写代码却不容易。可以换个思路:
对区间的右端点进行升序排序,每加入一个线段,然后选择后面一个或者多个右端点相同的区间,然后在选中区间内选择左端点最大的那一条,也就是区间最小的。如果加入以后不会跟之前的区间不会相互覆盖,那么就加入,否则就继续判断后面的区间
很简单吧,来看看代码咋写
代码实现
javascript
//倒序插入
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);
};
代码的思路,也就入上面描述中所讲的一样,代码就不做详细解释了。
其中有两个需要注意的地方,提一下
- 为了能够快速地在相同右端点的区间中,找到最大左端点的区间,可以采用有序插入的方式,这样就不用再对
tempArray
排序了 - 在找到若干个相同右端点的区间后,需要修改
i
的值,表示i
前面的区间已经被考虑过了。下一轮循环直接从i
后面的区间开始
测试代码
javascript
findManySpace(data);
// [ [ 2, 4 ], [ 6, 8 ], [ 8, 10 ] ]
输出正确
总结
本篇文章分享的是一道非常经典的区间求解问题,主要采用的策略是贪心算法。思路很简单,代码也很简单,难的是,如果不看答案之前,这道题根本做不出来....我在说我自己
说句题外话,写完这篇文章,我已经在算法和数据结构专题上分享了 50 余篇文章了,感觉仍在基础打转。数据结构是基础不假,但会了数据结构绝对不代表会算法,算法是解题方法,像数学题目一样,知识是知识,题目是题目,学会了知识,不代表会做题目。而且题目的解法,技巧是另一个层面的东西。
到现在,本专栏分享的数据结构涵盖了大学本科要求的所有数据,从数组,链表,到二叉树,二叉搜索树,多叉树,AVL 平衡树,B 树,(红黑树暂时没有), 图,集合,堆,hash表,分享的算法有排序算法,贪心算法,回溯算法,动态规划,对于浩如烟海的算法问题,这点很不够看。
刚去力扣试了试身手,结果被杀得卸甲归田...我还是在说我自己
难道要进入做一道会一道,不做就不会的怪圈么...给自己打了一个问号❓
题外话说完了,有问题可以评论区留言哦。我每天都会分享一篇算法小练习,喜欢就点赞+关注吧