题目 1 - 分发饼干
简介
题目 - 01: 分发饼干 (LeetCode 455)
题目 - 02: 摆动序列 (LeetCode 376)
题目 - 03: 最大子序和 (LeetCode 53)
题目 - 04: 买卖股票的最佳时机Ⅱ (LeetCode 122)
题目 - 05: 跳跃游戏 (LeetCode 55)
原题连接
题目描述
假设你是一位很棒的家长,想要给你的孩子们一些小饼干。但是,每个孩子最多只能给一块饼干。
对每个孩子
i,都有一个胃口值g[i],这是能让孩子们满足胃口的饼干的最小尺寸;并且每块饼 干j,都有一个尺寸s[j]。如果
s[j] >= g[i],我们可以将这个饼干j分配给孩子i,这个孩子会得到满足。你的目标是满足尽可能多的孩子,并输出这个最大数值。
思路
- 遍历小孩和饼干,都按从大到小优先匹配
- 优先将 大饼干 分配给 胃口大的孩子
- 如果该孩子可以被喂饱
- 可喂饱的数目 + 1
匹配条件:当前饼干刚好满足学生胃口,或者大于等于学生胃口. 匹配后遍历下一个饼干
如果无法匹配,继续遍历下一个学生
代码实现
class Solution {
public int findContentChildren(int[] g, int[] s) {
int m = g.length; // 小孩
int n = s.length; // 饼干
Arrays.sort(g); // 将小孩按照胃口从小到大排序
Arrays.sort(s); // 将饼干值按照从小到大排序
int sIdx = n - 1; // 遍历饼干,从大到小
int cnt = 0;
/*
遍历小孩和饼干,都按从大到小优先匹配
匹配条件:当前饼干刚好满足学生胃口,或者大于等于学生胃口. 匹配后遍历下一个饼干
如果无法匹配,继续遍历下一个学生
*/
for (int i = m - 1; i >= 0; i--) {
//
if (sIdx >= 0 && s[sIdx] >= g[i]) {
cnt++;
sIdx--; // 下一个饼干
}
}
return cnt;
}
}
执行结果
- 时间复杂度:
O(NlogN) - 空间复杂度:
O(1)
题目 2 - 摆动序列
原题连接
题目描述
如果连续数字之间的差严格地在正数和负数之间交替,则数字序列称为
摆动序列。第一个差(如果存在的话)可能是正数或负数。仅有一个元素或者含两个不等元素的序列也视作摆动序列。
例如,
[1, 7, 4, 9, 2, 5]是一个 摆动序列 ,因为差值 (6, -3, 5, -7, 3) 是正负交替出现的。相反,
[1, 4, 7, 2, 5]和[1, 7, 4, 5, 5]不是摆动序列,第一个序列是因为它的前两个差值都是正数,第二个序列是因为它的最后一个差值为零。
子序列: 可以通过从原始序列中删除一些(也可以不删除)元素来获得,剩下的元素保持其原始顺序。给你一个整数数组 nums ,返回 nums 中作为 摆动序列 的 最长子序列的长度 。
思路
- 要保证数组摆动,则相邻元素需要互为峰值,一个朝上一个朝下
- 对于长度小于 2 的序列,直接返回长度为
1 - 起始假设最右端始终为一个峰值
- 判断是否为一个峰值的条件:
- 前一次元素差值 记录
preDiff>= 0当前对元素的差值currDiff < 0; (即上一个峰值朝上,此时查询到朝下峰值) - 前一次元素差值记录
preDiff <= 0, 当前对的元素的差值currDiff > 0; (即上一个峰值朝下,此时查询到朝上峰值)
- 起始的时候差值为 0; 因此最少记录长度为 2
代码实现
public int wiggleMaxLength(int[] nums) {
if(nums.length < 2) {
return 1;
}
int ans = 1; //起始长度为 1
int preDiff = 0; //上一对元素的差值
int currDiff = 0; //当前对元素的差值
for(int i = 1; i < nums.length; i++) {
currDiff = nums[i] - nums[i - 1]; //当前差值
if((preDiff <= 0 && currDiff > 0) || (preDiff >= 0 && currDiff < 0)) {
ans++; //更新序列长度
preDiff = currDiff; //更新前一对峰值;
}
}
return ans;
}
执行结果
- 时间复杂度:
O(N) - 空间复杂度:
O(1)
题目 3 - 最大子数组和
原题连接
题目描述
给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
子数组 是数组中的一个连续部分。
思路
- 设区间总和为
sum - 分两种情况:
- 如果
sum >= 0, 则累加下一个元素可能得到更大值 - 如果此时
sum < 0已经成立,此区间和即使加上后序和为正数的区间和,最大值也是小于仅统计正数的区间和;因此直接更新为sum = 0后再记录
- 即当
sum < 0的时候,重置sum = 0后累加后续区间;如果sum >= 0还成立,继续尝试累加后续区间
代码实现
class Solution {
public int maxSubArray(int[] nums) {
int sum = nums[0];
int max = sum; // 记录最大值
for (int i = 1; i < nums.length; i++) {
if (sum < 0) { // 一个负数会导致和变小
sum = 0;
}
sum += nums[i];
max = Math.max(sum, max);
}
return max;
}
}
执行结果
- 时间复杂度:
O(N) - 空间复杂度:
O(1)
题目 4 - 买卖股票的最佳时机 Ⅱ
原题链接
题目描述
给你一个整数数组
prices,其中prices[i]表示某支股票第 i 天的价格。在每一天,你可以决定是否
购买和/或出售股票。你在任何时候 最多 只能持有 一股 股票。你也可以先购买,然后在 同一天 出售。 返回 你能获得的
最大利润 。
思路
- 想要利润最大,必须保证每笔隔 ? 天差价总和正数,每笔交易的差价也为正数
- 由于可以当天买卖,因此统计所有升区间,即
prices[i] - prices[i - 1] > 0的总和; 即为最大利润
代码实现
class Solution {
public int maxProfit(int[] prices) {
int max = 0;
for(int i = 1; i < prices.length; i++) {
//大于 0 即记录
max += Math.max(prices[i] - prices[i - 1], 0);
}
return max;
}
}
执行结果
- 时间复杂度:
O(N) - 空间复杂度:
O(1)