苏州网站建设姜超,免费注册工商,淄博微网站建设,天津建设网站的公司简介什么是贪心
贪心的本质是选择每一阶段的局部最优#xff0c;从而达到全局最优。
贪心算法一般分为如下四步#xff1a;
将问题分解为若干个子问题找出适合的贪心策略求解每一个子问题的最优解将局部最优解堆叠成全局最优解
1分发饼干
假设你是一位很棒的家长#xff0c…什么是贪心
贪心的本质是选择每一阶段的局部最优从而达到全局最优。
贪心算法一般分为如下四步
将问题分解为若干个子问题找出适合的贪心策略求解每一个子问题的最优解将局部最优解堆叠成全局最优解
1分发饼干
假设你是一位很棒的家长想要给你的孩子们一些小饼干。但是每个孩子最多只能给一块饼干。
对每个孩子 i都有一个胃口值 g[i]这是能让孩子们满足胃口的饼干的最小尺寸并且每块饼干 j都有一个尺寸 s[j] 。如果 s[j] g[i]我们可以将这个饼干 j 分配给孩子 i 这个孩子会得到满足。你的目标是尽可能满足越多数量的孩子并输出这个最大数值。 示例 1:
输入: g [1,2,3], s [1,1]
输出: 1
解释:
你有三个孩子和两块小饼干3个孩子的胃口值分别是1,2,3。
虽然你有两块小饼干由于他们的尺寸都是1你只能让胃口值是1的孩子满足。
所以你应该输出1。示例 2:
输入: g [1,2], s [1,2,3]
输出: 2
解释:
你有两个孩子和三块小饼干2个孩子的胃口值分别是1,2。
你拥有的饼干数量和尺寸都足以让所有孩子满足。
所以你应该输出2.提示
1 g.length 3 * 1040 s.length 3 * 1041 g[i], s[j] 231 - 1
思路 排序: 首先将孩子的胃口数组 g 和饼干的大小数组 s 分别按从小到大排序。这样做是为了能够从最小的胃口和最小的饼干开始匹配以尽可能满足更多的孩子。 贪心策略: 使用贪心算法的核心思想从胃口最大的孩子开始尝试给他们分配能满足他们胃口的最小饼干。这里的贪心选择是每次都选择当前能够满足的最小饼干以期望最终能够满足尽可能多的孩子。 实现细节: 使用 index 表示当前可用的饼干数组的最后一个元素的下标。从最大胃口的孩子开始向最小胃口的孩子遍历尝试找到合适的饼干分配。如果当前的饼干能够满足当前孩子的胃口则结果 result 加一并将 index 减一表示使用了这个饼干。如果当前的饼干不能满足当前孩子的胃口则继续向前尝试下一个更大的饼干直到找到合适的或者饼干用完。 返回结果: 最终返回 result即能够满足的孩子的数量。
代码
class Solution {
public:int findContentChildren(vectorint g, vectorint s) {// 将孩子数组和饼干数组按照从小到大排序sort(g.begin(), g.end()); // 按照孩子的胃口排序sort(s.begin(), s.end()); // 按照饼干的大小排序int index s.size() - 1; // 饼干数组的下标int result 0; // 结果能满足孩子的数量// 从胃口最大的孩子开始匹配饼干for (int i g.size() - 1; i 0; i--) { // 遍历胃口// 如果还有饼干可用且当前饼干满足当前孩子的胃口if (index 0 s[index] g[i]) { // 遍历饼干result; // 满足一个孩子index--; // 使用了一个饼干下标减一}}return result; // 返回满足孩子的数量}
};
2摆动序列
如果连续数字之间的差严格地在正数和负数之间交替则数字序列称为 摆动序列 。第一个差如果存在的话可能是正数或负数。仅有一个元素或者含两个不等元素的序列也视作摆动序列。 例如 [1, 7, 4, 9, 2, 5] 是一个 摆动序列 因为差值 (6, -3, 5, -7, 3) 是正负交替出现的。 相反[1, 4, 7, 2, 5] 和 [1, 7, 4, 5, 5] 不是摆动序列第一个序列是因为它的前两个差值都是正数第二个序列是因为它的最后一个差值为零。
子序列 可以通过从原始序列中删除一些也可以不删除元素来获得剩下的元素保持其原始顺序。
给你一个整数数组 nums 返回 nums 中作为 摆动序列 的 最长子序列的长度 。 示例 1
输入nums [1,7,4,9,2,5]
输出6
解释整个序列均为摆动序列各元素之间的差值为 (6, -3, 5, -7, 3) 。示例 2
输入nums [1,17,5,10,13,15,10,5,16,8]
输出7
解释这个序列包含几个长度为 7 摆动序列。
其中一个是 [1, 17, 10, 13, 10, 16, 8] 各元素之间的差值为 (16, -7, 3, -3, 6, -8) 。示例 3
输入nums [1,2,3,4,5,6,7,8,9]
输出2提示
1 nums.length 10000 nums[i] 1000
思路
代码
局部最优删除单调坡度上的节点不包括单调坡度两端的节点那么这个坡度就可以有两个局部峰值。
整体最优整个序列有最多的局部峰值从而达到最长摆动序列。只需要统计数组的峰值数量就可以了。 初始化 curDiff 初始化为 0表示当前一对相邻元素的差值。preDiff 也初始化为 0表示前一对相邻元素的差值。result 初始化为 1因为序列默认至少有一个峰值。 处理边界情况 如果数组 nums 的大小 1直接返回 nums.size()因为这种情况下不可能形成长度大于1的摆动序列。 遍历数组 循环遍历数组 nums从第一个元素到倒数第二个元素 (i nums.size() - 1)。 计算差值 计算 curDiff 为 nums[i 1] - nums[i]即当前两个相邻元素的差值。 检测峰值和谷值 当 preDiff 0 curDiff 0 或者 preDiff 0 curDiff 0 时表示出现了摆动的峰值或者谷值。在这些情况下增加 result 的计数因为它们是摆动序列的关键点。 返回结果 最终返回 result即最长摆动子序列的长度。 class Solution {
public:int wiggleMaxLength(vectorint nums) {if (nums.size() 1) return nums.size();int curDiff 0; // 当前一对差值int preDiff 0; // 前一对差值int result 1; // 记录峰值个数序列默认序列最右边有一个峰值for (int i 0; i nums.size() - 1; i) {curDiff nums[i 1] - nums[i];// 出现峰值if ((preDiff 0 curDiff 0) || (preDiff 0 curDiff 0)) {result;preDiff curDiff; // 注意这里只在摆动变化的时候更新prediff}}return result;}
};
3最大子数组和
给你一个整数数组 nums 请你找出一个具有最大和的连续子数组子数组最少包含一个元素返回其最大和。 子数组
是数组中的一个连续部分。 示例 1
输入nums [-2,1,-3,4,-1,2,1,-5,4]
输出6
解释连续子数组 [4,-1,2,1] 的和最大为 6 。示例 2
输入nums [1]
输出1示例 3
输入nums [5,4,-1,7,8]
输出23提示
1 nums.length 105-104 nums[i] 104
思路
局部最优当前“连续和”为负数的时候立刻放弃从下一个元素重新计算“连续和”因为负数加上下一个元素 “连续和”只会越来越小。
全局最优选取最大“连续和”
局部最优的情况下并记录最大的“连续和”可以推出全局最优。
该贪心算法实现的思路是在遍历数组的过程中持续累积子数组的元素和同时不断更新最大子数组之和。如果当前累积和变为负数就重新开始计算子数组和以期获得更大的子数组和。
代码
class Solution {
public:int maxSubArray(vectorint nums) {int result INT32_MIN; // 初始化最大和为负无穷int count 0; // 当前累积和for (int i 0; i nums.size(); i) {count nums[i]; // 累加当前元素到当前和if (count result) {result count; // 更新最大和为当前和}if (count 0) {count 0; // 如果当前和小于等于0则重新开始计算累积和}}return result; // 返回最大和}
};