Skip to content

Commit 5f3b753

Browse files
committed
add some greedy
1 parent 68d0871 commit 5f3b753

12 files changed

Lines changed: 563 additions & 0 deletions
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
设有n个活动的集合E={1,2,…,n},其中每个活动都要求使用同一资源,如演讲会场等,而在同一时间内只有一个活动能使用这一资源。
3+
每个活动i都有一个要求使用该资源的起始时间si和一个结束时间fi,且si <fi 。如果选择了活动i,则它在半开时间区间[si, fi)内占用资源。
4+
若区间[si, fi)与区间[sj, fj)不相交,则称活动i与活动j是相容的。也就是说,当si≥fj或sj≥fi时,活动i与活动j相容。
5+
6+
活动安排问题: 要在所给的活动集合中选出最大的相容活动子集合。
7+
8+
活动安排问题的关键是如何按照一定的顺序安排活动,使得选出的活动间相容并能安排尽量多的活动。
9+
10+
例:
11+
设待安排的11个活动的开始时间和结束时间按结束时间的非减序排列如下:
12+
13+
*/
14+
15+
package greedy;
16+
17+
import java.util.ArrayList;
18+
import java.util.List;
19+
20+
public class ActivityProblem {
21+
public static List<int[]> activityProblem(List<int[]> activities) {
22+
List<int[]> result = new ArrayList<>();
23+
activities.sort((x, y) -> {
24+
return x[1] - y[1];
25+
});
26+
result.add(activities.get(0));
27+
int[] pre = activities.get(0);
28+
for (int i = 1; i < activities.size(); i++) {
29+
int[] act = activities.get(i);
30+
if (act[0] > pre[1]) {
31+
result.add(act);
32+
pre = act;
33+
}
34+
}
35+
return result;
36+
}
37+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
455. 分发饼干
3+
假设你是一位很棒的家长,想要给你的孩子们一些小饼干。但是,每个孩子最多只能给一块饼干。
4+
对每个孩子 i ,都有一个胃口值 gi ,这是能让孩子们满足胃口的饼干的最小尺寸;并且每块饼干 j ,都有一个尺寸 sj 。
5+
如果 sj >= gi ,我们可以将这个饼干 j 分配给孩子 i ,这个孩子会得到满足。你的目标是尽可能满足越多数量的孩子,并输出这个最大数值。
6+
7+
注意:
8+
你可以假设胃口值为正。
9+
一个小朋友最多只能拥有一块饼干。
10+
11+
示例 1:
12+
输入: [1,2,3], [1,1]
13+
输出: 1
14+
15+
解释:
16+
你有三个孩子和两块小饼干,3个孩子的胃口值分别是:1,2,3。
17+
虽然你有两块小饼干,由于他们的尺寸都是1,你只能让胃口值是1的孩子满足。
18+
所以你应该输出1。
19+
示例 2:
20+
21+
输入: [1,2], [1,2,3]
22+
输出: 2
23+
解释:
24+
你有两个孩子和三块小饼干,2个孩子的胃口值分别是1,2。
25+
你拥有的饼干数量和尺寸都足以让所有孩子满足。
26+
所以你应该输出2.
27+
*/
28+
package greedy;
29+
30+
import java.util.Arrays;
31+
32+
public class AssignCookies {
33+
public int findContentChildren(int[] grid, int[] size) {
34+
if (grid == null || size == null) {
35+
return 0;
36+
}
37+
Arrays.sort(grid);
38+
Arrays.sort(size);
39+
int gi = 0;
40+
int si = 0;
41+
while (gi < grid.length && si < size.length) {
42+
if (size[si] >= grid[gi]) {
43+
gi++;
44+
}
45+
si++;
46+
}
47+
return gi;
48+
}
49+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*
2+
火车站台数量问题
3+
假设已知某个火车站的所有过往列车的到达arrival和离开departure时间(同一天),如果要求所有列车都不等待直接进站,问至少需要多少个站台。
4+
无需考虑晚点等特殊情况。
5+
6+
例如,
7+
Input:
8+
到达时间: arr[] = {9:00, 9:40, 9:50, 11:00, 15:00, 18:00}
9+
离开时间: dep[] = {9:10, 12:00, 11:20, 11:30, 19:00, 20:00}
10+
11+
Output:
12+
3 (最多有3辆列车同时进站(在11:00到11:20之间))
13+
*/
14+
package greedy;
15+
16+
import java.util.Arrays;
17+
18+
public class FindPlatForm {
19+
public static int findPlatform(int arr[], int dep[], int n) {
20+
Arrays.sort(arr);
21+
Arrays.sort(dep);
22+
23+
int result = 1;
24+
int currNeed = 1;
25+
int j = 0;
26+
for (int i = 1; i < arr.length; i++) {
27+
currNeed++;
28+
if (arr[i] > dep[j]) {
29+
while (j <= i && dep[j] < arr[i]) {
30+
currNeed--;
31+
j++;
32+
}
33+
}
34+
result = Math.max(currNeed, result);
35+
}
36+
return result;
37+
}
38+
39+
public static int findPlatform2(int arr[], int dep[], int n) {
40+
Arrays.sort(arr);
41+
Arrays.sort(dep);
42+
43+
int result = 0;
44+
int currNeed = 0;
45+
int i = 0;
46+
int j = 0;
47+
while (i < n && j < n) {
48+
if (arr[i] < dep[j]) {
49+
currNeed++;
50+
i++;
51+
result = Math.max(result, currNeed);
52+
} else {
53+
currNeed--;
54+
j++;
55+
}
56+
}
57+
return result;
58+
}
59+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*
2+
How to find the smallest number with given digit sum s and number of digits d?
3+
Examples :
4+
5+
Input : s = 9, d = 2
6+
Output : 18
7+
There are many other possible numbers
8+
like 45, 54, 90, etc with sum of digits
9+
as 9 and number of digits as 2. The
10+
smallest of them is 18.
11+
12+
Input : s = 20, d = 3
13+
Output : 299
14+
*/
15+
package greedy;
16+
17+
public class FindSmallest {
18+
public static int findSmallest(int sum, int m) {
19+
int result = 0;
20+
int curr = 1;
21+
while (sum > 0 && curr <= m) {
22+
for (int i = 1; i <= 9; i++) {
23+
if (sum - i <= (m - curr) * 9) {
24+
result += i * (int) Math.pow(10, (m - curr));
25+
sum -= i;
26+
break;
27+
}
28+
}
29+
curr++;
30+
}
31+
return result;
32+
}
33+
34+
/**
35+
* 贪心算法
36+
* @param sum
37+
* @param m
38+
* @return
39+
*/
40+
public static int findSmallest2(int sum, int m) {
41+
if (m <= 0) {
42+
return -1;
43+
}
44+
45+
if (sum > m * 9) {
46+
return -1;
47+
}
48+
49+
//预留1 给最高位
50+
int result = 0;
51+
sum -= 1;
52+
for (int i = m - 1; i > 0; i--) {
53+
if (sum >= 9) {
54+
result += 9 * (int) Math.pow(10, (m - i - 1));
55+
sum -= 9;
56+
} else {
57+
result += sum * (int) Math.pow(10, (m - i - 1));
58+
sum = 0;
59+
}
60+
}
61+
result += (1 + sum) * (int) Math.pow(10, m - 1);
62+
return result;
63+
}
64+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*
2+
134. 加油站
3+
在一条环路上有 N 个加油站,其中第 i 个加油站有汽油 gas[i] 升。
4+
5+
你有一辆油箱容量无限的的汽车,从第 i 个加油站开往第 i+1 个加油站需要消耗汽油 cost[i] 升。你从其中的一个加油站出发,开始时油箱为空。
6+
7+
如果你可以绕环路行驶一周,则返回出发时加油站的编号,否则返回 -1。
8+
9+
说明: 
10+
11+
如果题目有解,该答案即为唯一答案。
12+
输入数组均为非空数组,且长度相同。
13+
输入数组中的元素均为非负数。
14+
示例 1:
15+
16+
输入:
17+
gas = [1,2,3,4,5]
18+
cost = [3,4,5,1,2]
19+
20+
输出: 3
21+
22+
解释:
23+
从 3 号加油站(索引为 3 处)出发,可获得 4 升汽油。此时油箱有 = 0 + 4 = 4 升汽油
24+
开往 4 号加油站,此时油箱有 4 - 1 + 5 = 8 升汽油
25+
开往 0 号加油站,此时油箱有 8 - 2 + 1 = 7 升汽油
26+
开往 1 号加油站,此时油箱有 7 - 3 + 2 = 6 升汽油
27+
开往 2 号加油站,此时油箱有 6 - 4 + 3 = 5 升汽油
28+
开往 3 号加油站,你需要消耗 5 升汽油,正好足够你返回到 3 号加油站。
29+
因此,3 可为起始索引。
30+
示例 2:
31+
32+
输入:
33+
gas = [2,3,4]
34+
cost = [3,4,3]
35+
36+
输出: -1
37+
38+
解释:
39+
你不能从 0 号或 1 号加油站出发,因为没有足够的汽油可以让你行驶到下一个加油站。
40+
我们从 2 号加油站出发,可以获得 4 升汽油。 此时油箱有 = 0 + 4 = 4 升汽油
41+
开往 0 号加油站,此时油箱有 4 - 3 + 2 = 3 升汽油
42+
开往 1 号加油站,此时油箱有 3 - 3 + 3 = 3 升汽油
43+
你无法返回 2 号加油站,因为返程需要消耗 4 升汽油,但是你的油箱只有 3 升汽油。
44+
因此,无论怎样,你都不可能绕环路行驶一周。
45+
46+
*/
47+
package greedy;
48+
49+
public class GasStation {
50+
public int canCompleteCircuit(int[] gas, int[] cost) {
51+
int total = 0;
52+
int curr = 0;
53+
int start = 0;
54+
for (int i = 0; i < gas.length; i++) {
55+
total += gas[i] - cost[i];
56+
curr += gas[i] - cost[i];
57+
if (curr < 0) {
58+
curr = 0;
59+
start = i + 1;
60+
}
61+
}
62+
return total >= 0 ? start : -1;
63+
}
64+
}

src/main/java/greedy/JumpGame.java

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
55. 跳跃游戏
3+
给定一个非负整数数组,你最初位于数组的第一个位置。
4+
5+
数组中的每个元素代表你在该位置可以跳跃的最大长度。
6+
7+
判断你是否能够到达最后一个位置。
8+
9+
示例 1:
10+
11+
输入: [2,3,1,1,4]
12+
输出: true
13+
解释: 我们可以先跳 1 步,从位置 0 到达 位置 1, 然后再从位置 1 跳 3 步到达最后一个位置。
14+
示例 2:
15+
16+
输入: [3,2,1,0,4]
17+
输出: false
18+
解释: 无论怎样,你总会到达索引为 3 的位置。但该位置的最大跳跃长度是 0 , 所以你永远不可能到达最后一个位置。
19+
*/
20+
package greedy;
21+
22+
public class JumpGame {
23+
public static boolean canJump(int[] nums) {
24+
int need = 1;
25+
for (int i = nums.length - 2; i > 0; i--) {
26+
if (nums[i] >= need) {
27+
need = 1;
28+
} else {
29+
need++;
30+
}
31+
}
32+
return nums[0] >= need;
33+
}
34+
}

src/main/java/greedy/MinCoins.java

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
用给定的几种钱币凑成某个钱数
3+
例如:给定了6种钱币面值为2、5、10、20、50、100,用来凑 15元,可以用5个2元、1个5元,或者3个5元,或者1个5元、1个10元,等等。
4+
显然,最少需要2个钱币才能凑成15元
5+
6+
*/
7+
8+
package greedy;
9+
10+
import java.util.ArrayList;
11+
import java.util.Arrays;
12+
import java.util.List;
13+
14+
public class MinCoins {
15+
private static int[] coins = {1, 2, 5, 10, 20, 50, 100};
16+
17+
public static List<Integer> minCoins(int target) {
18+
List<Integer> result = new ArrayList<>();
19+
int index = coins.length - 1;
20+
while (target != 0) {
21+
if (target - coins[index] >= 0) {
22+
result.add(coins[index]);
23+
target = target - coins[index];
24+
} else {
25+
index--;
26+
}
27+
}
28+
return result;
29+
}
30+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package greedy;
2+
3+
import java.util.ArrayList;
4+
import java.util.Arrays;
5+
import java.util.List;
6+
7+
public class MinimumSum {
8+
public static int minimumSum(int[] nums) {
9+
if (nums == null || nums.length == 0) {
10+
return 0;
11+
}
12+
int num1 = 0;
13+
int num2 = 0;
14+
//排序 ---> 这步可以用堆来做 O(n)
15+
Arrays.sort(nums);
16+
for (int i = 0; i < nums.length; i++) {
17+
if (i % 2 == 0) {
18+
num1 = num1 * 10 + nums[i];
19+
} else {
20+
num2 = num2 * 10 + nums[i];
21+
}
22+
}
23+
return num1 + num2;
24+
}
25+
}

src/main/java/greedy/README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# 贪心算法
2+
3+
### 练习题
4+
* [找硬币](MinCoins.java)
5+
* [活动问题](ActivityProblem.java)
6+
* [最小的数字问题](FindSmallest.java)
7+
* [两个数字的最小和](MinimumSum.java)
8+
* [以最低的成本连接绳索](RopeCost.java)
9+
* [最小平台数](FindPlatForm.java)
10+
* [部分背包问题、分蛋糕](AssignCookies.java)
11+
* 将板子切割成正方形的最小成本
12+
* 字典中最小的数组
13+
* [加油站](GasStation.java)
14+
* [跳跃游戏](JumpGame.java)
15+
* [摆动序列](WiggleSubsequence.java)

0 commit comments

Comments
 (0)