系列文章目录
目录
- 系列文章目录
- 455.分发饼干
- 贪心算法
- 大饼干喂胃口大的(先遍历胃口)
- 胃口大的先吃大饼干(先遍历饼干)
- 小饼干先喂胃口小的(先遍历胃口)
- 胃口小的先吃小饼干(先遍历饼干)
- 376. 摆动序列
- 贪心算法
- 只关心上下坡摆动,对所有平坡忽略(总体看)[看了其他人的想法,好理解一些]
- 只关心节点左右的坡度(局部),若两边坡度相反则是峰值,考虑了平坡的情况[自己想不出来]
- 53. 最大子序和
- ①暴力解法(双层for循环,超时)
- ②贪心解法
455.分发饼干
贪心算法
大饼干喂胃口大的(先遍历胃口)
import java.util.Arrays;
class Solution {
public int findContentChildren(int[] g, int[] s) {
//先从小到大自然排序
Arrays.sort(g);
Arrays.sort(s);
int lenG = g.length;
int rightS = s.length - 1;
int count = 0;//记录满足的孩子个数
for (int i = lenG - 1; i >= 0; i--) {//遍历胃口
if (rightS >= 0 && s[rightS] >= g[i]) {// 遍历饼干(要先判断是否还有饼干再遍历)
count++;
rightS--;
}
}
return count;
}
}
胃口大的先吃大饼干(先遍历饼干)
import java.util.Arrays;
class Solution {
public int findContentChildren(int[] g, int[] s) {
//先从小到大自然排序
Arrays.sort(g);
Arrays.sort(s);
int rightG = g.length - 1;
int count = 0;
for (int i = s.length - 1; i >= 0; i--) {
while (rightG >= 0) {
if (s[i] >= g[rightG]) {
count++;
rightG--;
break;
}
rightG--;
}
}
return count;
}
}
小饼干先喂胃口小的(先遍历胃口)
import java.util.Arrays;
class Solution {
public int findContentChildren(int[] g, int[] s) {
Arrays.sort(g);
Arrays.sort(s);
int count = 0;
int leftS = 0;
for (int i = 0; i < g.length; i++) {
while (leftS < s.length) {
if (s[leftS] >= g[i]) {
count++;
leftS++;
break;
}
leftS++;
}
}
return count;
}
}
胃口小的先吃小饼干(先遍历饼干)
import java.util.Arrays;
class Solution {
public int findContentChildren(int[] g, int[] s) {
Arrays.sort(g);
Arrays.sort(s);
int count = 0;
int leftG = 0;
for (int i = 0; i < s.length; i++) {
if (leftG < g.length &&s[i]>=g[leftG]){
count++;
leftG++;
}
}
return count;
}
}
376. 摆动序列
贪心算法
只关心上下坡摆动,对所有平坡忽略(总体看)[看了其他人的想法,好理解一些]
class Solution {
int mark = 0;// 记录是否出现摆动,没出现摆动为0,出现摆动后上坡为1,下坡为-1
int count = 1;//因1 <= nums.length <= 1000,故最少有一个元素
public int wiggleMaxLength(int[] nums) {
// nums.length = 1或2的情况可以包含在下面for循环中
// if (nums.length == 1) return 1; // 不进入for循环,直接返回1
// if (nums.length == 2) return nums[0] == nums[1] ? 1 : 2; // 有摆动才返回2,否则返回1
// 策略:只有第一次出现摆动,以及上下坡的转折点的时候,才res++
for (int i = 1; i < nums.length; i++) {
int prediff = nums[i] - nums[i - 1];
// 如果之前都没出现摆动(第一次出现摆动)
if (mark == 0) {
if (prediff > 0) {// 第一次出现的摆动为上坡
mark = 1;
count++;
}
if (prediff < 0) {// 第一次出现的摆动为下坡
mark = -1;
count++;
}
//平坡代表没有摆动,不处理
}
// 如果遇到上坡,判断上一个摆动是否为下坡,是再记录结果并更新摆动
if (prediff > 0 && mark == -1) {
mark = 1;// 记录上坡
count++;
}
// 如果遇到下坡,判断上一个摆动是否为上坡,是再记录结果并更新摆动
if (prediff < 0 && mark == 1) {
mark = -1;// 记录下坡
count++;
}
// 注意:此处包含对了平坡的忽略
}
return count;
}
}
只关心节点左右的坡度(局部),若两边坡度相反则是峰值,考虑了平坡的情况[自己想不出来]
class Solution {
int count = 1;//默认最右面有一个峰值
int prediff = 0;
public int wiggleMaxLength(int[] nums) {
for (int i = 0; i < nums.length - 1; i++) {
int curdiff = nums[i + 1] - nums[i];//i节点右边坡度
// 出现峰值
if (prediff >= 0 && curdiff < 0 || prediff <= 0 && curdiff > 0) {
count++;
prediff = curdiff;
}
}
return count;
}
}
53. 最大子序和
①暴力解法(双层for循环,超时)
第一层 for
就是设置起始位置,第二层 for
循环遍历数组寻找最大值。
class Solution {
int sum = 0;
int maxSum = Integer.MIN_VALUE;//将最大和先置为int的最小值
public int maxSubArray(int[] nums) {
for (int i = 0; i < nums.length; i++) {
sum = 0;//每遍历一个节点先将sum置为0
for (int j = i; j < nums.length; j++) {
sum += nums[j];
maxSum = sum > maxSum ? sum : maxSum;
}
}
return maxSum;
}
}
②贪心解法
思路:
- 局部最优:每遍历一个元素,都记录着截止到当前元素的最大子数组和(当前元素不一定是最大子数组和对应子数组的结尾)。
- 全局最优:遍历到最后一个元素,就相当于获得了全局最大子数组和。
maxSum
要初始化为最小负数,因数组可能全是负数,初始化为0
会导致最大和为0
。
class Solution {
int sum = 0;
int maxSum = Integer.MIN_VALUE;//将最大和先置为int的最小值
public int maxSubArray(int[] nums) {
for (int i = 0; i < nums.length; i++) {
sum += nums[i];
if (sum > maxSum) maxSum = sum;// 取区间累计的最大值(相当于不断确定最大子序终止位置)
if (sum <= 0) {
sum = 0; // 相当于重置最大子序起始位置,因为遇到负数一定是拉低总和
}
}
return maxSum;
}
}