算法集锦

1、贪心算法

一、区间相关问题:选择不相交的区间java

数轴上有n个开区间(begin,end),尽可能选择数量最多的区间,使得这些区间两两没有交集。【某国王打算让将军们去守卫长城(可当作一条线段),每一个人选择一个本身喜欢的区间段,为了让最多的将军能守卫本身想守卫的地方,怎么安排是最合理的呢?例如:长城的区间段是[1,1000],每一个将军选择的区间段都在这个范围内,任意两个将军守卫的地方不能有重合的地方,不然会出现争执,两个点的交集不算交集】算法

好比输入:ide

 1 2 324   
 2 320 424
 3 259 342
 4 371 888
 5 264 634
 6 909 982
 7 117 653
 8 677 929
 9 656 707
10 297 915
11 904 943
12 309 564
13 564 601
14 675 876
15 33 89
16 363 912
17 226 952
18 86 129
19 216 339
20 258 857

则对应输出this

第1个区间段为[33,89]
第2个区间段为[216,339]
第3个区间段为[564,601]
第4个区间段为[656,707]
第5个区间段为[904,943]
最多有5个区间段

解题思路:使用贪心算法,贪心策略为按照end从小到大的顺序将全部区间进行排序,每次取与以前的区间不相交的第一个区间spa

public class Changcheng implements Comparable<Changcheng>{
    private int begin;
    private int end;
    
    public Changcheng(int begin, int end) {
        this.begin = begin;
        this.end = end;
    }
    
    public int getBegin() {
        return begin;
    }
    public void setBegin(int begin) {
        this.begin = begin;
    }
    public int getEnd() {
        return end;
    }
    public void setEnd(int end) {
        this.end = end;
    }

    @Override
    public int compareTo(Changcheng o) {
        if(this.getEnd() > o.getEnd()) {
            return 1;
        }else if(this.getEnd() < o.getEnd()) {
            return -1;
        }
        return 0;
    }
}
import java.util.Arrays;

public class Solution {
    public static void main(String[] args) {
        Changcheng[] changcheng = new Changcheng[20];
        changcheng[0] = new Changcheng(2, 324);
        changcheng[1] = new Changcheng(320, 424);
        changcheng[2] = new Changcheng(259, 342);
        changcheng[3] = new Changcheng(371, 888);
        changcheng[4] = new Changcheng(264, 634);
        changcheng[5] = new Changcheng(909, 982);
        changcheng[6] = new Changcheng(117, 653);
        changcheng[7] = new Changcheng(677, 929);
        changcheng[8] = new Changcheng(656, 707);
        changcheng[9] = new Changcheng(297, 915);
        changcheng[10] = new Changcheng(904, 943);
        changcheng[11] = new Changcheng(309, 564);
        changcheng[12] = new Changcheng(564, 601);
        changcheng[13] = new Changcheng(675, 876);
        changcheng[14] = new Changcheng(33, 89);
        changcheng[15] = new Changcheng(363, 912);
        changcheng[16] = new Changcheng(226, 952);
        changcheng[17] = new Changcheng(86, 129);
        changcheng[18] = new Changcheng(216, 339);
        changcheng[19] = new Changcheng(258, 857);
        
        process(changcheng);
    }
    
    private static void process(Changcheng[] changcheng) {
        //按照end从小到大的顺序将全部区间进行排序
        Arrays.sort(changcheng);
        
        int end = changcheng[0].getEnd();
        int count = 1;
        System.out.println("" + count + "个区间段为[" + changcheng[0].getBegin() + "," + end + "]");
        for(int i=1; i<changcheng.length; i++) {
            //寻找不相交的区间
            if(changcheng[i].getBegin() >= end) {
                count++;
                end = changcheng[i].getEnd();
                System.out.println("" + count + "个区间段为[" + changcheng[i].getBegin() + "," + end + "]");
            }
        }
        System.out.println("最多有" + count + "个不重复的区间段");
    }
}

二、区间相关问题:区间选点问题code

数轴上有n个闭区间[begin,end],取尽可能少的点,使得每一个区间内都至少有一个点(不一样区间内含的点能够是同一个)blog

例如输入:排序

[0, 3]
[16, 20]
[2, 8]
[8, 21]
[15, 17]
[10, 12]
[19, 21]

输出get

第1个点为:3
第2个点为:12
第3个点为:17
第4个点为:21
最少须要选择4个点

解题思路:使用贪心算法,贪心策略为按照end从小到大的顺序将区间排序(end相同时,begin从大到小排序),则若是出现区间包含的状况,小区间必定排在前面,每一个区间取最后一个点。io

public class Changcheng implements Comparable<Changcheng>{
    private int begin;
    private int end;
    
    public Changcheng(int begin, int end) {
        this.begin = begin;
        this.end = end;
    }
    
    public int getBegin() {
        return begin;
    }
    public void setBegin(int begin) {
        this.begin = begin;
    }
    public int getEnd() {
        return end;
    }
    public void setEnd(int end) {
        this.end = end;
    }

    //按照end从小到大的顺序将区间排序(end相同时,begin从大到小排序)
    @Override
    public int compareTo(Changcheng o) {
        if(this.getEnd() > o.getEnd()) {
            return 1;
        }else if(this.getEnd() < o.getEnd()) {
            return -1;
        }else {
            if(this.getBegin() > o.getBegin()) {
                return -1;
            }else if(this.getBegin() < o.getBegin()) {
                return 1;
            }
            return 0;
        }
    }
    
    //判断当前区间是否包含指定点
    public boolean contains(int point) {
        if(point >= this.getBegin() && point <= this.getEnd()) {
            return true;
        }
        return false;
    }
}
import java.util.Arrays;

public class Solution {
    public static void main(String[] args) {
        Changcheng[] changcheng = new Changcheng[7];
        changcheng[0] = new Changcheng(0, 3);
        changcheng[1] = new Changcheng(16, 20);
        changcheng[2] = new Changcheng(2, 8);
        changcheng[3] = new Changcheng(8, 21);
        changcheng[4] = new Changcheng(15, 17);
        changcheng[5] = new Changcheng(10, 12);
        changcheng[6] = new Changcheng(19, 21);
        
        process(changcheng);
    }
    //区间选点问题
    private static void process(Changcheng[] changcheng) {
        Arrays.sort(changcheng);
        
        int count = 1;
        int point = changcheng[0].getEnd();
        System.out.println("" + count + "个点为:" + point);
        for(int i=1; i<changcheng.length; i++) {
            if(!changcheng[i].contains(point)) {
                point = changcheng[i].getEnd();
                count++;
                System.out.println("" + count + "个点为:" + point);
            }
        }
        System.out.println("最少须要选择" + count + "个点");
    }
}
相关文章
相关标签/搜索