0%

Greddy Algorithm

贪心算法采用贪心的策略,保证每步都是局部最优,最终达到全局最优

分配问题

455.Assign Cookies (Easy)

题目描述

  有一群孩子和一堆饼干,每个孩子都有一个饥饿度,每个饼干都有一个大小,每个孩子只能吃最多一个饼干,且只有饼干的大小大于孩子的饥饿度时,这个孩子才能吃饱。求解最多有多少孩子可以吃饱。

输入输出样例

  输入两个数组,分别代表孩子们的饥饿度和饼干的大小。输出最多有多少孩子可以吃饱的数量。

1
2
Input: [1, 2], [1, 2, 3]
Output: 2  

c++:

1
2
3
4
5
6
7
8
9
10
int findContentChildren(vector<int>& children, vector<int>& cookies) {
sort(children.begin(), children.end());
sort(cookies.begin(), cookies.end());
int child = 0, cookie = 0;
while (child < children.size() && cookie < cookies.size()) {
if (children[child] <= cookies[cookie]) ++child;
++cookie;
}
return child;
}

java:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Solution {
public int findContentChildren(int[] g, int[] s) {
int max = 0;
Arrays.sort(g);
Arrays.sort(s);
for (int i = 0, j = 0; i < s.length & j < g.length; i++) {
if (g[j] <= s[i]) {
max++;
j++;
}
}
return max;
}
}
  1. Candy(Hard)

题目描述

   一群孩子站成一排,每一个孩子有自己的评分。现在需要给这些孩子发糖果,规则是如果一个孩子的评分比自己身旁的一个孩子要高,那么这个孩子就必须得到比身旁孩子更多的糖果;所有的孩子至少要有一个糖果。求解最少需要多少个糖果。

输入输出样例

输入是一个数组,表示孩子的评分。输出是最少糖果的数量。
1
2
Input: [1, 0, 2]
Output: 5

c++:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int candy(vector<int>& ratings) {
int size = ratings.size();
if (size < 2) {
return size;
}
vector<int> num(size, 1);
for (int i = 1; i < size; ++i) {
if (ratings[i] > ratings[i - 1])
num[i] = ratings[i - 1] + 1;
}
for (int i = size - 1; i > 0; --i) {
if (ratings[i] < ratings[i - 1])
num[i - 1] = max(num[i - 1], num[i] + 1);
}
return accumulate(num.begin(), num.end(), 0);
}

java:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Solution {
public int candy(int[] ratings) {
int[] rating = new int[ratings.length];
Arrays.fill(rating, 1);
for (int i = 1; i < rating.length; i++) {
if (ratings[i] > ratings[i - 1]) {
rating[i] = rating[i - 1] + 1;
}
}
for (int i = rating.length - 2; i >= 0; i--) {
if (ratings[i] > ratings[i + 1]) {
rating[i] = Math.max(rating[i + 1] + 1, rating[i]);
}
}
int sum = 0;
for (int rat : rating) {
sum += rat;
}
return sum;
}
}

区间问题

  1. Non-overlapping Intervals (Medium)

题目描述

  给定多个区间,计算这些区间互不重叠所需要移除区间的最小个数,起止相连不算重叠。

输入输出样例

输入是一个数组,数组由多个长度固定为2的数组组成,表示区间的开始和结尾。输出一个整数,表示需要移除的区间数量。
1
2
Input: [[1, 2], [2, 4], [1, 3]]
Output: 1

c++:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
int eraseOverlapIntervals(vector<vector<int>>& intervals) {
if (intervals.empty()) {
return 0;
}
std::sort(intervals.begin(), intervals.end(), [](vector<int> a, vector<int>b) {
return a[1] < b[1];
});
int total = 0, prev = intervals[0][1];
for (int i = 1; i < intervals.size(); ++i) {
if (intervals[i][0] < prev) {
total += 1;
} else {
prev = intervals[i][1];
}
}
return total;
}

java:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
//时间复杂度O(NlogN)
//主要时间花在排序上
class Solution {
public int eraseOverlapIntervals(int[][] intervals) {
// 12,13,23,34
int invals = 0;
if (intervals.length <= 0) {
return invals;
}
Arrays.sort(intervals, new Comparator<int[]>() {
@Override
public int compare(int[] o1, int[] o2) {
return o1[1] - o2[1];
}
});
int[] interval = intervals[0];
int max = 1;
for (int i = 1; i < intervals.length; i++) {
if (interval[1] <= intervals[i][0]) {
interval = intervals[i];
max++;
}
if(interval[1] > intervals[i][1]){
interval = intervals[i];
}
}
return intervals.length - max;
}
}
//主要时间花费在两层循环上
//时间复杂度O(n^2)
class Solution {
public int eraseOverlapIntervals(int[][] intervals) {
// 12,13,23,34
int invals = 0;
if (intervals.length <= 0) {
return invals;
}
Arrays.sort(intervals, new Comparator<int[]>() {
@Override
public int compare(int[] o1, int[] o2) {
return o1[0] - o2[0];
}
});
int[] nums = new int[intervals.length];
Arrays.fill(nums, 1);
for (int i = 1; i < intervals.length; i++) {
for (int j = 0; j < i; j++) {
if (intervals[j][1] <= intervals[i][0]) {
nums[i] = Math.max(nums[i], nums[j] + 1);
}
}
}
int max = 0;
for (int i = 0; i < nums.length; i++) {
max = Math.max(max, nums[i]);
}
return nums.length - max;
}
}