定义
贪心算法(又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,算法得到的是在某种意义上的局部最优解。
贪心算法或贪心思想采用贪心的策略,保证每次操作都是局部最优的,从而使最后得到的结果是全局最优的。
455. Assign Cookies分配饼干 (Easy)
Assume you are an awesome parent and want to give your children some cookies. But, you should give each child at most one cookie.
Each child i
has a greed factor g[i]
, which is the minimum size of a cookie that the child will be content with; and each cookie j
has a size s[j]
. If s[j] >= g[i]
, we can assign the cookie j
to the child i
, and the child i
will be content. Your goal is to maximize the number of your content children and output the maximum number.
有一群孩子和一堆饼干,每个孩子有一个饥饿度,每个饼干都有一个大小。每个孩子只能吃一个饼干,且只有饼干的大小不小于孩子的饥饿度时,这个孩子才能吃饱。求解最多有多少孩子可以吃饱。
输入两个数组,分别代表孩子的饥饿度和饼干的大小。输出最多有多少孩子可以吃饱的数量。
Example 1:
Input: g = [1,2,3], s = [1,1]
Output: 1
Explanation: You have 3 children and 2 cookies. The greed factors of 3 children are 1, 2, 3.
And even though you have 2 cookies, since their size is both 1, you could only make the child whose greed factor is 1 content.
You need to output 1.
Example 2:
Input: g = [1,2], s = [1,2,3]
Output: 2
Explanation: You have 2 children and 3 cookies. The greed factors of 2 children are 1, 2.
You have 3 cookies and their sizes are big enough to gratify all of the children,
You need to output 2.
Constraints:
- 1 <= g.length <= 3 * 104
- 0 <= s.length <= 3 * 104
- 1 <= g[i], s[j] <= 231 - 1
思路
这里使用贪心策略,不断将最小饥饿度的孩子分配最小且能吃饱的饼干。因为需要获得大小关系,所以使用数组的sort()方法,这样就可以的到最小饥饿度的孩子和最小的饼干。
代码
class Solution {
public int findContentChildren(int[] g, int[] s) {
Arrays.sort(g);
Arrays.sort(s);
int g1=0, s1=0;
while (g1 < g.length && s1 < s.length) {
if (g[g1] <= s[s1]) ++g1;
++s1;
}
return g1;
}
}
135 Candy 糖果(Hard)
There are n
children standing in a line. Each child is assigned a rating value given in the integer array ratings.
You are giving candies to these children subjected to the following requirements:
Each child must have at least one candy.
Children with a higher rating get more candies than their neighbors.
Return the minimum number of candies you need to have to distribute the candies to the children.
一群孩子站成一排,每一个孩子有自己的评分。现在需要给这些孩子发糖果,规则是如果一个孩子的评分比自己身旁的一个孩子要高,那么这个孩子就必须得到比身旁孩子更多的糖果;所有孩子至少要有一个糖果。求解最少需要多少个糖果。
输入是一个数组,表示孩子的评分。输出是最少糖果的数量。
Example 1:
Input: ratings = [1,0,2]
Output: 5
Explanation: You can allocate to the first, second and third child with 2, 1, 2 candies respectively.
Example 2:
Input: ratings = [1,2,2]
Output: 4
Explanation: You can allocate to the first, second and third child with 1, 2, 1 candies respectively.
The third child gets 1 candy because it satisfies the above two conditions.
Constraints:
- n == ratings.length
- 1 <= n <= 2 * 104
- 0 <= ratings[i] <= 2 * 104
思路
题目需要求出最少分配所需的糖果数。运用贪心算法,只需要两次遍历即可,建立数组a,设初始值a[0]=1,先从左往右遍历,若右边大于左边,则右边的数为左边孩子糖果数加一,否则右边孩子糖果数为1。第二次从右往左遍历,若左边孩子评分比右边孩子高,且左边孩子糖果不大于右边孩子,则左边孩子糖果数变为右边孩子糖果数加一。贪心策略为每次遍历只考虑相邻一侧的大小关系。
代码
class Solution {
public int candy(int[] ratings) {
int size = ratings.length;
if (size < 2) {
return size;
}
int[] a = new int[size];
a[0] = 1;
for (int i =1; i < size; ++i) {
if (ratings[i] > ratings[i-1]) {
a[i] = a[i-1] + 1;
} else a[i] =1;
}
for (int i = size-1; i > 0; --i) {
if (ratings[i] < ratings[i-1]) {
a[i-1] = Math.max(a[i-1], a[i] +1);
}
}
int sum = 0;
for( int num : a) {
sum = sum + num;
}
return sum;
}
}
435 Non-overlapping Intervals 无重叠区间 (Medium)
Given an array of intervals intervals where intervals[i] = [starti, endi]
, return the minimum number of intervals you need to remove to make the rest of the intervals non-overlapping.
给定多个区间,计算让这些区间互不重叠所需要移除区间的最少个数。起止相连不算重叠。
输入是一个数组,数组由多个长度固定为 2 的数组组成,表示区间的开始和结尾。输出一个整数,表示需要移除的区间数量。
Example 1:
Input: intervals = [[1,2],[2,3],[3,4],[1,3]]
Output: 1
Explanation: [1,3] can be removed and the rest of the intervals are non-overlapping.
Example 2:
Input: intervals = [[1,2],[1,2],[1,2]]
Output: 2
Explanation: You need to remove two [1,2] to make the rest of the intervals non-overlapping.
Example 3:
Input: intervals = [[1,2],[2,3]]
Output: 0
Explanation: You don’t need to remove any of the intervals since they’re already non-overlapping.
Constraints:
- 1 <= intervals.length <= 2 * 104
- intervals[i].length == 2
- -2 * 104 <= starti < endi <= 2 * 104
思路
解题思路为选择区间的结尾越小,留给其他区间的空间就越大。因此贪心策略为优先保留结尾小且与前一个区间不重叠的区间。
首先将不同区间按照结尾的大小进行增序排序,然后每次选择结尾最小且与前一个区间不重叠的区间。
ps:intervals[0][1]
代表第一个区间的结尾元素,而intervals[i][0]
代表下一个区间的开始元素。
代码
class Solution {
public int eraseOverlapIntervals(int[][] intervals) {
if (intervals.length == 0) {
return 0;
}
int n =intervals.length;
Arrays.sort(intervals, new Comparator<int[]>(){
public int compare(int[] interval1, int[] interval2){
return interval1[1] - interval2[1];
}
});
int total = 0;
int prev = intervals[0][1];
for (int i = 1; i < n; ++i) {
if (intervals[i][0] < prev){
++total;
} else {
prev = intervals[i][1];
}
}
return total;
}
}