LeetCode 455 分发饼干
题目描述
假设你是一位很棒的家长,想要给你的孩子们一些小饼干。但是,每个孩子最多只能给一块饼干。
对每个孩子 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.
思路
这道题目可以先固定饼干的数量,然后找到能满足的最大的小孩胃口,也可以先固定要满足的小孩胃口,再找能满足他胃口的最小饼干数量。这里我们选择先从最大的胃口开始for循环遍历,如果饼干数大于等于小孩的胃口,再遍历下一个饼干,否则就一直找更小的胃口,直到胃口小于这个饼干数为止。
代码实现
class Solution {
public:int findContentChildren(vector<int>& g, vector<int>& s) {sort(g.begin(),g.end());sort(s.begin(),s.end());int result = 0;int index = s.size() - 1;for(int i = g.size() - 1;i >= 0;i--){if(index >= 0 && s[index] >= g[i]){result++;index--;}}return result;}
};
LeetCode 376 摆动序列
题目描述
如果连续数字之间的差严格地在正数和负数之间交替,则数字序列称为 摆动序列 。第一个差(如果存在的话)可能是正数或负数。仅有一个元素或者含两个不等元素的序列也视作摆动序列。
-
例如,
[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
思路
本题的基本思路是判断与前一个数的结果<0,同时与后一个数相减的结果>0,或者反过来,就可以记录一个峰值。
需要注意的细节一:如果前后的元素有平坡,这时候三个2中有一个需要记录为峰值,但是左右两边始终有一边的增长数量或者是减小数量为0,这时候就需要将判断条件改为
nums[i] - nums[i - 1] <= 0 && nums[i + 1] - nums[i] > 0
或者
nums[i] - nums[i - 1] <= 0 && nums[i + 1] - nums[i] > 0
细节二:结尾默认记录为一个峰值,同时开头只要第二个数不和第一个数相等,就可以记录为一个峰值。
细节三:单调有平坡的情况
例如[1,2,2,2,3,4],如图:
图中,我们可以看出按照先前的思路,会在2这个地方记录一个峰值,因为 单调中的平坡 不能算峰值(即摆动)。所以为了避免这种情况,更新prediff的条件要有变化,只有curdiff有变化的时候,才更新prediff,如果curdiff一直是平坡,那么就不更新prediff。并且因为默认了最后一个数是一个峰值,所以curdiff = 0,prediff不等于0的情况不能记录峰值。
代码实现
class Solution {
public:int wiggleMaxLength(vector<int>& nums) {if(nums.size() <= 1) return nums.size();int prediff = 0;int result = 1;int curdiff = 0;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++;}if(curdiff != 0) prediff = curdiff;}return result;}
};
LeetCode 53 最大子序和
题目描述
给你一个整数数组 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
思路
本题的思路是遍历整个数组,当子序列的和小于0时,就重新开始加和,同时每遍历一个数,如果子序列和,大于当前result中存放的数,都要更新result的值。
代码实现
class Solution {
public:int maxSubArray(vector<int>& nums) {int sum = 0;int result = nums[0];for(int i = 0; i < nums.size();i++){sum += nums[i];if(sum > result) result = sum;if(sum < 0) sum = 0;}return result;}
};
LeetCode 122 买卖股票的最佳时机II
题目描述
给你一个整数数组 prices
,其中 prices[i]
表示某支股票第 i
天的价格。
在每一天,你可以决定是否购买和/或出售股票。你在任何时候 最多 只能持有 一股 股票。你也可以先购买,然后在 同一天 出售。
返回 你能获得的 最大 利润 。
示例 1:
输入:prices = [7,1,5,3,6,4] 输出:7 解释:在第 2 天(股票价格 = 1)的时候买入,在第 3 天(股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5 - 1 = 4 。随后,在第 4 天(股票价格 = 3)的时候买入,在第 5 天(股票价格 = 6)的时候卖出, 这笔交易所能获得利润 = 6 - 3 = 3 。总利润为 4 + 3 = 7 。
示例 2:
输入:prices = [1,2,3,4,5] 输出:4 解释:在第 1 天(股票价格 = 1)的时候买入,在第 5 天 (股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5 - 1 = 4 。总利润为 4 。
示例 3:
输入:prices = [7,6,4,3,1] 输出:0 解释:在这种情况下, 交易无法获得正利润,所以不参与交易可以获得最大利润,最大利润为 0 。
思路
这道题的思路可以简化为和上一题类似的思路,算出每一个相邻数的差值,只累加正数,就可以得到最大利润。
假如第 0 天买入,第 3 天卖出,那么利润为:prices[3] - prices[0]。
相当于(prices[3] - prices[2]) + (prices[2] - prices[1]) + (prices[1] - prices[0])。
此时就是把利润分解为每天为单位的维度,而不是从 0 天到第 3 天整体去考虑!
不管是哪一天购入,哪一天卖出,只要在赚了钱,将赚得的钱数累加起来,就可以得到最大的利润。
代码实现
class Solution {
public:int maxProfit(vector<int>& prices) {int result = 0;for(int i = 1; i < prices.size();i++){if(prices[i] - prices[i - 1] > 0){result += prices[i] - prices[i - 1];}}return result;}
};