第八章 贪心算法 part01
理论基础
455.分发饼干
https://programmercarl.com/0455.%E5%88%86%E5%8F%91%E9%A5%BC%E5%B9%B2.html
思路1:优先考虑饼干,小饼干先喂饱小胃口
- 首先,使用Arrays.sort(g)和Arrays.sort(s)对两个数组g和s进行排序,将它们从小到大排列,以便后续的分配。
- 然后,定义两个变量start和count,start用于记录已经满足胃口的孩子的数量,count用于记录满足胃口的孩子的总数。
- 使用一个for循环遍历数组s,表示遍历每一个饼干。
- 在循环中,首先判断start是否小于数组g的长度,并且判断当前饼干s[i]的大小是否能够满足孩子的胃口g[start]。
- 如果满足条件,表示当前饼干可以满足当前孩子的胃口,将start和count都加1,表示已经满足了一个孩子的需求。
- 循环结束后,返回count,即为满足胃口的孩子的总数。
这个算法的思路是优先考虑饼干,将饼干从小到大排序,然后遍历每一个饼干,看是否能够满足孩子的胃口,如果能够满足,则计数器加1,同时更新start指针,表示已经满足了一个孩子的需求。最后返回计数器的值,即为满足胃口的孩子的总数。
Java
class Solution {
// 思路1:优先考虑饼干,小饼干先喂饱小胃口
public int findContentChildren(int[] g, int[] s) {
Arrays.sort(g);
Arrays.sort(s);
int start = 0;
int count = 0;
for (int i = 0; i < s.length && start < g.length; i++) {
if (s[i] >= g[start]) {
start++;
count++;
}
}
return count;
}
}
完整代码
package leetcode.editor.cn;
import java.util.*;
class ID455AssignCookies{
public static void main(String[] args) {
int[] g = {1, 4, 3};
int[] s = {1, 2};
Solution solution = new Solution();
int maxCount = solution.findContentChildren(g, s);
System.out.println("最大满足孩子数量:" + maxCount);
}
//leetcode submit region begin(Prohibit modification and deletion)
static class Solution {
public int findContentChildren(int[] g, int[] s) {
Arrays.sort(g);
Arrays.sort(s);
int start = 0;
int count = 0;
for (int i = 0; i < s.length && start < g.length; i++) {
if (s[i] >= g[start]) {
start++;
count++;
}
}
return count;
}
}
//leetcode submit region end(Prohibit modification and deletion)
}
思路2:优先考虑胃口,先喂饱大胃口
class Solution {
// 思路2:优先考虑胃口,先喂饱大胃口
public int findContentChildren(int[] g, int[] s) {
Arrays.sort(g);
Arrays.sort(s);
int count = 0;
int start = s.length - 1;
// 遍历胃口
for (int index = g.length - 1; index >= 0; index--) {
if(start >= 0 && g[index] <= s[start]) {
start--;
count++;
}
}
return count;
}
}
376. 摆动序列
https://programmercarl.com/0376.%E6%91%86%E5%8A%A8%E5%BA%8F%E5%88%97.html
Java
class Solution {
public int wiggleMaxLength(int[] nums) {
if (nums.length <= 1) {
return nums.length;
}
//当前差值
int curDiff = 0;
//上一个差值
int preDiff = 0;
int count = 1;
for (int i = 1; i < nums.length; i++) {
//得到当前差值
curDiff = nums[i] - nums[i - 1];
//如果当前差值和上一个差值为一正一负
//等于0的情况表示初始时的preDiff
if ((curDiff > 0 && preDiff <= 0) || (curDiff < 0 && preDiff >= 0)) {
count++;
preDiff = curDiff;
}
}
return count;
}
}
// DP
class Solution {
public int wiggleMaxLength(int[] nums) {
// 0 i 作为波峰的最大长度
// 1 i 作为波谷的最大长度
int dp[][] = new int[nums.length][2];
dp[0][0] = dp[0][1] = 1;
for (int i = 1; i < nums.length; i++){
//i 自己可以成为波峰或者波谷
dp[i][0] = dp[i][1] = 1;
for (int j = 0; j < i; j++){
if (nums[j] > nums[i]){
// i 是波谷
dp[i][1] = Math.max(dp[i][1], dp[j][0] + 1);
}
if (nums[j] < nums[i]){
// i 是波峰
dp[i][0] = Math.max(dp[i][0], dp[j][1] + 1);
}
}
}
return Math.max(dp[nums.length - 1][0], dp[nums.length - 1][1]);
}
}
53. 最大子序和
https://programmercarl.com/0053.%E6%9C%80%E5%A4%A7%E5%AD%90%E5%BA%8F%E5%92%8C.html
Java
class Solution {
public int maxSubArray(int[] nums) {
if (nums.length == 1){
return nums[0];
}
int sum = Integer.MIN_VALUE;
int count = 0;
for (int i = 0; i < nums.length; i++){
count += nums[i];
sum = Math.max(sum, count); // 取区间累计的最大值(相当于不断确定最大子序终止位置)
if (count <= 0){
count = 0; // 相当于重置最大子序起始位置,因为遇到负数一定是拉低总和
}
}
return sum;
}
}
// DP 方法
class Solution {
public int maxSubArray(int[] nums) {
int ans = Integer.MIN_VALUE;
int[] dp = new int[nums.length];
dp[0] = nums[0];
ans = dp[0];
for (int i = 1; i < nums.length; i++){
dp[i] = Math.max(dp[i-1] + nums[i], nums[i]);
ans = Math.max(dp[i], ans);
}
return ans;
}
}