贪心算法,java,leetcode笔记

分配问题

455.分发饼干
排序 + 先考虑需求小(大)的

135.分发糖果
1.两次遍历
每次只考虑相邻的糖果数目与评分是否相符

public int candy(int[] ratings) {
        int n = ratings.length;
        if(n < 2)
            return n;
        int[] result = new int[n];        
        result[0] = 1;
        // 从左往右第一次遍历
        for(int i = 1; i < n;i++){
            if(ratings[i - 1] < ratings[i]){
                result[i] = result[i - 1] + 1;
            }
            else{
                result[i] = 1;
            }
        }
        // 从右往左第二次遍历
        int sum = result[n - 1];
        for(int i = n - 1;i >= 1;i--){
            if(ratings[i - 1] > ratings[i] && result[i - 1] <= result[i]){
                result[i - 1] = result[i] + 1;
            }
            sum += result[i - 1];
        }
        return sum;
    }

2.常数空间遍历
从左到右枚举每一个同学,记前一个同学分得的糖果数量为 pre:

如果当前同学比上一个同学评分高,说明我们就在最近的递增序列中,直接分配给该同学 pre+1 个糖果即可。

否则我们就在一个递减序列中,我们直接分配给当前同学一个糖果,并把该同学所在的递减序列中所有的同学都再多分配一个糖果,以保证糖果数量还是满足条件。

我们无需显式地额外分配糖果,只需要记录当前的递减序列长度,即可知道需要 额外分配的糖果数量。

同时注意当当前的递减序列长度和上一个递增序列等长时,需要把最近的递增序列的最后一个同学也并进递减序列中。

这样,我们只要记录当前递减序列的长度 dec,最近的递增序列的长度 inc 和前一个同学分得的糖果数量 pre 即可。

int n = ratings.length;
if(n < 2)
    return n;
int sum = 1, pre = 1, dec = 0, inc = 1;
for(int i = 1; i < n ; i++){
    if(ratings[i - 1] <= ratings[i]){
        //递增序列
        pre =  ratings[i - 1] == ratings[i] ? 1 : pre + 1;
        sum += pre;
        dec = 0;
        inc = pre;
    }else{
        //递减序列
        dec++;
        if(inc == dec){
            dec++;
        }
        sum += dec;
        pre = 1;
    }
}
return sum;

区间问题
435.无重叠区间
给定多个区间,计算让这些区间互不重叠所需要移除区间的最少个数。起止相连不算重叠。

按区间右端点大小升序
如果排列区间左端点,要降序排列

```java
public int eraseOverlapIntervals(int[][] intervals) {
    if(intervals.length == 0)
        return 0;
    //定制排序
    Arrays.sort(intervals,new Comparator<int[]>(){
        public int compare(int[] interval1, int[] interval2){
            return interval1[1] - interval2[1];
        } 
    });
    
    int n = intervals.length;
    int right = intervals[0][1];
    int cnt = 1;
    for(int i = 1; i < n; i++){
        if(right <= intervals[i][0]){
            cnt++;
            right = intervals[i][1];
        }
    }
    return n - cnt;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值