java 贪心算法(无重复区间)
*************************
贪心算法
算法描述:原问题可拆解为多阶段进行,每个阶段都做出当前阶段的最优选择(当前阶段最优不一定是全局最优)
适用场景:如果当前阶段做出的选择是否为全局最优与后续阶段的选择无关(无后效性),则可使用贪心算法
不适用示例:三角形最短路径和
贪心算法解:2 ==> 3 ==> 5 ==> 1,为全局最优解
贪心算法解:2 ==> 3 ==> 60 ==> 1,不是全局最优解
全局最优解:2 ==> 4 ==> 7 ==> 3
三角形最短路径当前阶段的解是否为全局最优解与后续阶段的选取有关(即存在后效性),不可用贪心算法
*************************
示例:无重复区间
问题描述
给定一个区间集合,找到需要一处的区间的最小数量,使得剩余的空间不重叠
注意:可以假定区间的终点总是大于区间的起点;
区间[1,2]、[2,3]有接触,但是不重叠
示例 1:[1,2], [2,3], [3,4], [1,3]
输出:1, 移除[1,3]后,剩余区间不重叠
示例 2:[1,2], [1,2], [1,2]
输出:2,移除2个[1,2]后,剩余区间不重叠
示例 3:[1,2], [2,3]
输出:0, 原始区间不重叠
贪心算法:将区间按end排序,再按start排序
从第一个区间开始,遍历后面的区间,如果第一个区间与后面的区间重叠,移除后面的区间;
从第二个区间开始,遍历后面的区间,如果第二个区间与后面的区间重叠,移除后面的区间;
重复执行上述过程,直至比较所有区间
class Interval implements Comparable<Interval> {
private Integer start;
private Integer end;
public Integer getStart() {
return start;
}
public void setStart(Integer start) {
this.start = start;
}
public Integer getEnd() {
return end;
}
public void setEnd(Integer end) {
this.end = end;
}
@Override
public int compareTo(Interval o) {
if (this.getEnd()<o.getEnd()){
return -1;
}
if (this.getEnd()>o.getEnd()){
return 1;
}
return this.getStart().compareTo(o.getStart());
}
@Override
public String toString() {
return "["+this.getStart()+","+this.getEnd()+"] ";
}
}
public class MyTest {
public static List<Interval> generate(int num){
Random random=new Random();
List<Interval> list=new ArrayList<>();
for (int i=0;i<num;i++){
Interval interval=new Interval();
int start=random.nextInt(100);
int end=start+random.nextInt(20)+1;
interval.setStart(start);
interval.setEnd(end);
list.add(interval);
}
return list;
}
public static void main(String[] args){
List<Interval> list=generate(10);
System.out.println("初始区间为:");
list.forEach(System.out::print);
Collections.sort(list);
System.out.println("\n\n区间排序后:");
list.forEach(System.out::print);
int count=0;
for (int i=0;i<list.size()-1;i++){
for (int j=i+1;j<list.size();){
if (list.get(i).getEnd()>list.get(j).getStart()){
list.remove(j);
count++;
}else {
j++;
}
}
}
System.out.println("\n\n移除的区间数为:"+count);
System.out.println("移除后区间为:");
list.forEach(System.out::print);
}
}
控制台输出
初始区间为:
[77,80] [86,88] [68,79] [93,113] [44,62] [28,31] [57,65] [32,49] [89,100] [66,67]
区间排序后:
[28,31] [32,49] [44,62] [57,65] [66,67] [68,79] [77,80] [86,88] [89,100] [93,113]
移除的区间数为:3
移除后区间为:
[28,31] [32,49] [57,65] [66,67] [68,79] [86,88] [89,100]