系列文章目录
目录
- 系列文章目录
- 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,下坡为-1int 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置为0for (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;}
}