贪心算法
选择当前最好的情况走过去 (短视) 每次选择局部最优解 然后最后走到全局最优解 但是只能是单峰的情况下,才可以使用贪心 。 多峰的情况下 就通过这个够呛找到全局最优解。
两种模板(区间选点,最大不相交区间数)按照右端点排序,两种模板(区间覆盖,区间分组)按照左端点排序。
一、区间选点
给定 N 个闭区间 [ai,bi],请你在数轴上选择尽量少的点,使得每个区间内至少包含一个选出的点。
输出选择的点的最小数量。
位于区间端点上的点也算作区间内。
输入格式
第一行包含整数 N,表示区间数。
接下来 N 行,每行包含两个整数 ai,bi,表示一个区间的两个端点。
输出格式
输出一个整数,表示所需的点的最小数量。
数据范围
1≤N≤105,
−109≤ai≤bi≤109
输入样例:
3
-1 1
2 4
3 5
输出样例:
2
1.题解-时间复杂度 O(nlogn)
题目理解
1、一般区间问题都会排序 我们都会按照区间右端点排序 从小到大排序
2、从前往后依次枚举每个区间 都枚举区间的右端点end 初始化是无穷小 分情况讨论: 如果当前区间中已经包含点,则直接pass , else 选择当前区间的右端点
此题的最优解就是所有解决方案中的最小值
ans <= cnt cnt表示一个可行解的点数
证明的话就是 A <= B B >= A -> A =B
证明:
(1)找到cnt个点,满足题意情况,则最优解Ans <= cnt
(2)找到cnt个点,即找到cnt个区间,区间内没有交集的话 ,则说明可能有区间没有被这cnt个点覆盖过,所以最优解Ans >= cnt
综上:Ans == cnt
代码如下(示例):
import java.io.*;
import java.util.*;
public class Main {
static final int N = (int)1e5 + 10;
static int n;
static Node[] range = new Node[N];
static class Node {
int l, r;
public Node(int l, int r) {
this.l = l;
this.r = r;
}
}
public static void main(String[] args) throws IOException {
BufferedReader put =new BufferedReader(new InputStreamReader(System.in));
String arr = put.readLine();
n = Integer.parseInt(arr);
int a, b;
for (int i = 0; i < n; ++i) {
String[] cur = put.readLine().split(" ");
a = Integer.parseInt(cur[0]);
b = Integer.parseInt(cur[1]);
range[i] = new Node(a, b);
}
Arrays.sort(range, 0, n, (o1, o2) -> o1.r - o2.r);//按照右端点排序
//这里面用的是数组排序 也可以用Collections 、 list 等
//但是排序l 用以上式子方便 或者这种 Collections.sort(list);
int t = Integer.MIN_VALUE, cnt = 0;
for (int i = 0; i < n; ++i) {
if (range[i].l > t) {//如果当前点不能覆盖这个区间 就Pass else就更新这个点 并且cnt+1
t = range[i].r;//选择右端点
++cnt;
}
}
System.out.println(cnt + " ");
}
}