135、分发糖果
基本思想:
贪心算法
具体实现:
确定一个维度再去确定另一个维度
A确定右边评分大于左边评分(从前向后遍历),和自己的左边孩子比
局部最优:只要右边评分比左边大,右边的孩子就多一个糖果
全局最优:相邻的孩子中,评分高的右孩子获得比左孩子更多的糖果
如果ratings[i] > ratings[i - 1] ,那么[i]的糖一定要比[i - 1]的糖多一个
贪心:candyVec[i] = candyVec[i - 1] + 1
B确定左边评分大于右边评分(从后向前遍历),和自己右边孩子比
如果从前向后遍历,根据 ratings[i + 1] 来确定 ratings[i] 对应的糖果,那么每次都不能利用上第一次的比较结果了。
如果ratings[i] > ratings[i + 1] ,candyVec[i]有两个选择,
一个是candyVec[i + 1] + 1(从右边这个加1得到的糖果数量),
一个是candyVec[i](之前比较右孩子大于左孩子得到的糖果数量)
局部最优:只要左边评分比右边大,取candyVec[i + 1] + 1 和 candyVec[i] 最大的糖果数量,保证第i个小孩的糖果数量即大于左边的也大于右边的。
全局最优:相邻的孩子中,评分高的孩子获得更多的糖果。
贪心:candyVec[i] = candyVec[i + 1] + 1
代码:
class Solution { public int candy(int[] ratings) { int[] candy = new int[ratings.length]; for (int i = 0; i < candy.length; i++){ candy[i] = 1; } for (int i = 1; i < ratings.length; i++){ if (ratings[i] > ratings[i-1]){ candy[i] = candy[i-1] + 1; } } for (int i = ratings.length - 2; i >= 0; i--){ if (ratings[i] > ratings[i+1]){ candy[i] = Math.max(candy[i],candy[i + 1] + 1); } } int count = 0; for (int i = 0; i < candy.length; i++){ count += candy[i]; } return count; } }
406、根据身高重建队列
基本思想:
贪心算法
具体实现:
确定一个维度再去确定另一个维度
1.先按身高排序
2.按照身高高的k来插入,后续插入节点也不会影响前面已经插入的节点
局部最优:按照身高高的k来插入。插入操作过后的people满足队列特性
全局最优:最后都做完插入操作,整个队列满足题目队列属性
举例:
排序过后的people:[[7,0], [7,1], [6,1], [5,0], [5,2],[4,4]]
插入过程
插入[7,0]:[7,0]
插入[7,1]:[7,0],[7,1]
插入[6,1]:[7,0],[6,1],[7,1]
插入[5,0]:[5,0],[7,0],[6,1],[7,1]
插入[5,2]:[5,0],[7,0],[5,2],[6,1],[7,1]
插入[4,4]:[5,0],[7,0],[5,2],[6,1],[4,4],[7,1]
代码:
class Solution { public int[][] reconstructQueue(int[][] people) { // 身高从大到小排(身高相同k小的站前面) Arrays.sort(people, (a, b) -> { if (a[0] == b[0]) return a[1] - b[1]; return b[0] - a[0]; }); LinkedList<int[]> que = new LinkedList<>(); for (int[] p : people) { que.add(p[1],p); } return que.toArray(new int[people.length][]); } }