Skip to content

Latest commit

 

History

History
289 lines (246 loc) · 7.82 KB

6_贪心.md

File metadata and controls

289 lines (246 loc) · 7.82 KB

贪心思想

1、连续子数组的最大和

连续子数组的最大和

//思路:
//贪心策略:遍历数组,到当前位置,上次保留的最大值如果为负数就要刷新一次,
// 即 curSum<=0时,当即果断丢弃,因为只会越加越小,刷新为当前值;
// 如果为正数,继续累加。

public int FindGreatestSumOfSubArray(int[] array) {
    if (array == null || array.length == 0){
        return 0;
    }
    int curSum = 0;
    int res= Integer.MIN_VALUE;
    for(int i=0;i<array.length;i++){
        if(curSum<=0){
            curSum = array[i];
        }else{
            curSum += array[i];
        }
        res = Math.max(res,curSum);
    }
    return res;
}

2、买卖股票的时机

买卖股票的时机

//思路:
// 贪心策略
// 假设第 i 轮进行卖出操作,买入操作价格应该在 i 之前并且价格最低。
public int maxProfit(int[] prices) {
    int n = prices.length;
    if(n==0 || n==1){
        return 0;
    }
    int minValue = prices[0];
    //初始时,不进行交易,当然收益为0
    int maxProfit  = 0 ;
    for(int i=1;i<n;i++){
        minValue = Math.min(minValue,prices[i]); //在 i 轮卖出前,以最低价格买入
        maxProfit = Math.max(maxProfit,prices[i]-minValue); //贪心策略:每轮都买出
    }
    return maxProfit;
}

3、分发饼干

分发饼干

// 思路:
// 贪心策略:每次选取最大的饼干给最“贪心"”的小朋友。
public int findContentChildren(int[] g, int[] s) {
    if(g==null || s==null){
        return 0;
    }
    Arrays.sort(g);
    Arrays.sort(s);
    int i=g.length-1;
    int j=s.length-1;
    int num=0;
    while (i>=0 && j>=0){
        if(s[j]>=g[i]){
            num++;
            j--;
        }
        i--;
    }
    return num;
}

4、救生艇

救生艇

// 思路:
// 贪心策略:
// 将最重的人和最轻的安排在同一艘船上
// 如果只能载一个人,则载最重的,如果剩下一个人,则只能单独趁一艘船。
public int numRescueBoats(int[] people, int limit) {
    if(people==null || people.length==0 || limit<=0){
        return 0;
    }
    Arrays.sort(people);
    int light=0;
    int heavy=people.length-1;
    int res=0;
    while (light<=heavy){
        if(light==heavy){ // 只剩下一个人,则单独一艘船
            res++;
            break;
        }
        if(people[light]+people[heavy]>limit){ // 如果只能载一个人,则载最重的
            res++;
            heavy--;
        }else{ // people[light]+people[heavy]<=limit,船可以搭载两个人
            res++;
            light++;
            heavy--;
        }
    }
    return res;
}

*5、汇总区间

汇总区间

public List<String> summaryRanges(int[] nums) {
    List<String> res=new ArrayList<>();
    if(nums==null || nums.length==0){
        return res;
    }
    if(nums.length==1) {
        res.add(nums[0] + "");
        return res;
    }
    int start=nums[0];
    int end=start;
    for(int i=1;i<nums.length;i++){
        if(nums[i]==end+1){
            end++;
        }else{
            res.add(buildInterval(start,end));
            start=nums[i];
            end=start;
        }
    }
    res.add(buildInterval(start,end));
    return res;
}

private String buildInterval(int start,int end){
    if(start==end){
        return start+"";
    }
    return start+"->"+end;
}

6、无重叠区间

无重叠区间

// 思路:
// 首先计算最多能组成的不重叠区间个数,然后用区间总个数减去不重叠区间的个数。
// 其中区间结尾至关重要,选择的区间结尾越小,留给后面的空间就越大,那么后面能够选择的区间个数也就越大。
public int eraseOverlapIntervals(int[][] intervals) {
    if(intervals==null || intervals.length==0){
        return 0;
    }
    // 按照区间结尾进行升序排序
    // 写法一:比较器
    // 这里使用 p1[1]<p2[1]?-1:((p1[1]==p2[1])?0:1),没有使用 p1[1]-p2[1],这是因为两数相减存在溢出的情况
    /*Arrays.sort(intervals, new Comparator<int[]>() {
            @Override
            public int compare(int[] p1, int[] p2) {
                return p1[1]<p2[1]?-1:((p1[1]==p2[1])?0:1);
            }
        });*/
    // 写法二:使用正则表达式,
    Arrays.sort(intervals,
                (p1,p2)-> p1[1]<p2[1]?-1:((p1[1]==p2[1])?0:1));
    // 写法三:JDK8简化写法
    /*Arrays.sort(intervals, Comparator.comparingInt(p->p[1]));*/
    int cnt=1; // 记录最大不重叠区间数
    int end=intervals[0][1]; // 记录前一个不重叠区间结尾位置
    for(int i=1;i<intervals.length;i++){
        if(intervals[i][0]<end){ // 重叠区间,注意这里 [1,2]和[2,3]不算重叠区间
            continue;
        }
        cnt++;
        end=intervals[i][1];
    }
    return intervals.length-cnt;
}

7、用最少数量的箭引爆气球

用最少数量的箭引爆气球

// 思路:本质上就是计算不重叠的区间个数,注意这里[1,2]和[2,3]属于重叠区间
public int findMinArrowShots(int[][] points) {
    if(points==null || points.length==0){
        return 0;
    }
    // 按区间结尾位置从小到大排序
    // 写法一:比较器
    /*Arrays.sort(points, new Comparator<int[]>() {
            @Override
            public int compare(int[] o1, int[] o2) {
                return o1[1]<o2[1]?-1:(o1[1]==o2[1]?0:1);
            }
        });*/
    // 写法二:正则表达式
    //Arrays.sort(points,(o1,o2)->(o1[1]<o2[1]?-1:(o1[1]==o2[1])?0:1));
    // 写法三:JDK8 简化写法
    Arrays.sort(points,Comparator.comparingInt(o->o[1]));
    int res=1;
    int end=points[0][1];
    for(int i=1;i<points.length;i++){
        if(points[i][0]<=end){ // 注意这里[1,2]和[2,3]属于重叠区间
            continue;
        }
        res++;
        end=points[i][1];
    }
    return res;
}

*8、合并区间

合并区间

public int[][] merge(int[][] intervals) {
    if(intervals==null || intervals.length==1){
        return intervals;
    }
    // 按照开始位置从小到大进行排序
    // 写法一:比较器
    Arrays.sort(intervals, new Comparator<int[]>() {
        @Override
        public int compare(int[] o1, int[] o2) {
            return (o1[0]<o2[0])?-1:o1[0]==o2[0]?0:1;
        }
    });
    // 写法二:Lambda 表达式
    /*Arrays.sort(intervals,(o1,o2)->
                o1[0]<o2[0]?-1:o1[0]==o2[0]?0:1);*/
    // 写法三:JDK8 简化写法
    /*Arrays.sort(intervals, Comparator.comparingInt(o->o[0]));*/
    List<int[]> intervalList=new ArrayList<>(); // 保存结果区间
    int[] cur=intervals[0]; // 记录当前重叠区间
    int m=intervals.length;
    for(int i=1;i<m;i++){
        if(cur[1]>=intervals[i][0]){ // cur.end >= next.start
            cur[1]=Math.max(cur[1],intervals[i][1]);
        }else{
            intervalList.add(cur);
            cur=intervals[i];
        }
        if(i==m-1){
            intervalList.add(cur);
        }
    }
    int[][] res=new int[intervalList.size()][2];
    for(int i=0;i<intervalList.size();i++){
        int[] interval=intervalList.get(i);
        res[i][0]=interval[0];
        res[i][1]=interval[1];
    }
    return res;
}