分配问题
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;
}