1. 分配饼干

455. 分发饼干

题目描述:每个孩子都有一个满足度 grid,每个饼干都有一个大小 size,只有饼干的大小大于等于一个孩子的满足度,该孩子才会获得满足。求解最多可以获得满足的孩子数量。

class Solution {
public int findContentChildren(int[] g, int[] s) {
Arrays.sort(g);
Arrays.sort(s);
int i=0,j=0;
while(i<g.length && j<s.length){
if(g[i]<=s[j]){
i++;
j++;
}
else{
j++;
}
}
return i;
}
}

2. 不重叠的区间个数

435. 无重叠区间

这个是经典的贪心算法,典型的不能再典型

先计算最多能组成的不重叠区间个数,然后用区间总个数减去不重叠区间的个数。

核心思想就是选结束时间最早的。

class Solution {
public int eraseOverlapIntervals(int[][] intervals) {
int n = intervals.length;
return n - intervalSchedule(intervals);
}
public int intervalSchedule(int[][] intvs){
if(intvs.length==0)return 0;
Arrays.sort(intvs,new Comparator<int[]>(){
public int compare(int[] a,int[] b){
return a[1]-b[1];
}
});
int count=1;
int x_end=intvs[0][1];
for(int[] interval:intvs){
int start=interval[0];
if(start>=x_end){
count++;
x_end=interval[1];
}
}
return count;
}
}

学习一下lamada表达式

注意大数的问题

class Solution {
public int eraseOverlapIntervals(int[][] intervals) {
int n = intervals.length;
return n - intervalSchedule(intervals);
}
public int intervalSchedule(int[][] intvs){
if(intvs.length==0)return 0;
Arrays.sort(intvs, (a,b)->(a[1]-b[1]));
int count=1;
int x_end=intvs[0][1];
for(int[] interval:intvs){
int start=interval[0];
if(start>=x_end){
count++;
x_end=interval[1];
}
}
return count;
}
}

3. 投飞镖刺破气球

452. 用最少数量的箭引爆气球

题目描述:气球在一个水平数轴上摆放,可以重叠,飞镖垂直投向坐标轴,使得路径上的气球都被刺破。求解最小的投飞镖次数使所有气球都被刺破。

也是计算不重叠的区间个数,不过和 Non-overlapping Intervals 的区别在于,[1, 2] 和 [2, 3] 在本题中算是重叠区间。

Arrays.sort(intervals, Comparator.comparingInt(o -> o[1]));
class Solution {
public int findMinArrowShots(int[][] points) {
int n=points.length;
if(n==0)return 0;
Arrays.sort(points,(a,b)->(a[1]-b[1]));
int count=1;
int end=points[0][1];
for(int[] arr:points){
int start=arr[0];
if(start>end){
count++;
end=arr[1];
}
}
return count;
}
}

4. 根据身高和序号重组队列

注意点为高个子是无法注意矮个子的,并且矮个子无法改变高个子的身高索引数值k

身高 h 降序、个数 k 值升序,然后将某个学生插入队列的第 k 个位置中。

406. 根据身高重建队列

class Solution {
public int[][] reconstructQueue(int[][] people) {
if(people==null||people.length==0||people[0].length==0){
return new int[0][0];
}
Arrays.sort(people,(a,b)->(a[0]==b[0]?a[1]-b[1]:b[0]-a[0]));
List<int[]>queue=new ArrayList<>();
for(int[] p:people){
queue.add(p[1],p);
}
return queue.toArray(new int[queue.size()][]); }
}

5. 买卖股票最大的收益

class Solution {
public int maxProfit(int[] prices) {
int max=0;
for(int i=0;i<prices.length;i++){
for(int j=i;j<prices.length;j++){
int index=prices[j]-prices[i];
if(max<index)max=index;
}
}
return max;
}
}

只要记录前面的最小价格,将这个最小价格作为买入价格,然后将当前的价格作为售出价格,查看当前收益是不是最大收益。

public int maxProfit(int[] prices) {
int n = prices.length;
if (n == 0) return 0;
int soFarMin = prices[0];
int max = 0;
for (int i = 1; i < n; i++) {
if (soFarMin > prices[i]) soFarMin = prices[i];
else max = Math.max(max, prices[i] - soFarMin);
}
return max;
}

6. 买卖股票的最大收益 II

122. 买卖股票的最佳时机 II

对于 [a, b, c, d],如果有 a <= b <= c <= d ,那么最大收益为 d - a。而 d - a = (d - c) + (c - b) + (b - a) ,因此当访问到一个 prices[i] 且 prices[i] - prices[i-1] > 0,那么就把 prices[i] - prices[i-1] 添加到收益中。

class Solution {
public int maxProfit(int[] prices) {
if(prices.length==0)return 0;
int max = 0;
for(int i = 1; i < prices.length; i++){
if(prices[i]>prices[i - 1]){
max += prices[i] - prices[i - 1];
}
}
return max; }
}

7. 种植花朵

605. 种花问题

public class Solution {
public boolean canPlaceFlowers(int[] flowerbed, int n) {
int i = 0, count = 0;
while (i < flowerbed.length) {
if (flowerbed[i] == 0 && (i == 0 || flowerbed[i - 1] == 0) && (i == flowerbed.length - 1 || flowerbed[i + 1] == 0)) {
flowerbed[i] = 1;
count++;
}
i++;
}
return count >= n;
}
}

8. 判断是否为子序列

392. 判断子序列

class Solution {
public boolean isSubsequence(String s, String t) {
if(s.length()==0)return true;
int i = 0,j = 0;
while(j<t.length() && i<s.length()){
if(s.charAt(i)==t.charAt(j)){
i++;
}
j++;
}
if(i==s.length())return true;
return false;
}
}
public boolean isSubsequence(String s, String t) {
int index = -1;
for (char c : s.toCharArray()) {
index = t.indexOf(c, index + 1);
if (index == -1) {
return false;
}
}
return true;
}

9. 修改一个数成为非递减数组

665. 非递减数列

思路要清洗,具体分析多种情况

这道题给了我们一个数组,说我们最多有1次修改某个数字的机会,
  问能不能将数组变为非递减数组。题目中给的例子太少,不能覆盖所有情况,我们再来看下面三个例子:
    4,2,3
    -1,4,2,3
    2,3,3,2,4
我们通过分析上面三个例子可以发现,当我们发现后面的数字小于前面的数字产生冲突后,

  1. 有时候需要修改前面较大的数字(比如前两个例子需要修改4),
  2. 有时候却要修改后面较小的那个数字(比如前第三个例子需要修改2),

那么有什么内在规律吗?是有的,判断修改那个数字其实跟再前面一个数的大小有关系,
首先如果再前面的数不存在,比如例子1,4前面没有数字了,我们直接修改前面的数字为当前的数字2即可。
而当再前面的数字存在,并且小于当前数时,比如例子2,-1小于2,我们还是需要修改前面的数字4为当前数字2;
如果再前面的数大于当前数,比如例子3,3大于2,我们需要修改当前数2为前面的数3。

class Solution {
public boolean checkPossibility(int[] nums) {
int cnt=0;
for(int i=1; i < nums.length && cnt < 2; i++){
if(nums[i]>=nums[i-1])continue;
cnt++;
if(i-2>=0 && nums[i-2] > nums[i]){
nums[i]=nums[i-1];
}
else{
nums[i-1]=nums[i];
}
}
return cnt <= 1;
}
}

10. 子数组最大的和

53. 最大子序和

梦开始的题

class Solution {
public int maxSubArray(int[] nums) {
if(nums == null ||nums.length == 0){
return 0;
}
int presum=nums[0];
int maxsum=presum;
for(int i=1; i<nums.length; i++){
presum=presum>0?presum+nums[i]:nums[i];
maxsum=Math.max(maxsum,presum);
}
return maxsum; }
}

思路
假设[i,j]为我们所寻找的子序列
nums[left,right]考虑任何连续子数组nums[i,j]必然位于下列三种情况 method(getMaxSubArray(int[] nums,int left,int right)
1. 完全位于子数组nums[left,mid]中,因此left<=i<=j<=mid
2. 完全位于子数组nums[mid+1,right]中,因此mid+1<=i<=j<=right
3. 跨越了中点,因此left<=i<=mid<=j<=right
4. 比较三种情况 返回最大值
关键在于情况3 如何对于跨越中点子序列求解(其实并不难) 其实就是两侧最大子序列和相加 method public int midSumMax(int left,int mid,int right,int[] nums)
1. 求出以mid为定点,从mid down to left 的子序列 [i,mid] 也就是leftMaxSum;
2. 求出以mid+1为定点,从mid+1 up to right 的子序列 [mid+1,j] 也就是RightMaxSum;
3. 求和leftMaxSum+RightMaxSum 从而得出中间最大子序列和

class Solution {
public int maxSubArray(int[] nums) {
return getMaxSubArray(nums,0,nums.length-1);
}
public int getMaxSubArray(int[] nums,int left,int right){
if (left==right){
return nums[left];
}else{
int mid=(left+right)/2;
int leftMax=getMaxSubArray(nums,left,mid);//求左边子序列的最大值(情况1)
int rightMax=getMaxSubArray(nums,mid+1,right);//求右边子序列的最大值(情况2)
int midMax=midSumMax(left,mid,right,nums);//求跨越终点子序列最大值(情况3)
//逐一进行比较,返回最大值
if (leftMax>=rightMax&&leftMax>=midMax){
return leftMax;
}else if (rightMax>=leftMax&&rightMax>=midMax){
return rightMax;
}else{
return midMax;
}
}
}
//跨越中点子序列求解
public int midSumMax(int left,int mid,int right,int[] nums){
int Sum=0;
int leftMaxSum=Integer.MIN_VALUE;
//mid为定点,左边最大子序和
for (int i=mid;i>=left;i--){
Sum+=nums[i];
leftMaxSum= Math.max(leftMaxSum,Sum);
}
Sum=0;
//mid+1为顶点,右边最大子序和
int rightMaxSum=Integer.MIN_VALUE;
for (int i=mid+1;i<=right;i++){
Sum+=nums[i];
rightMaxSum=Math.max(rightMaxSum,Sum);
}
return leftMaxSum+rightMaxSum;
}
}

11. 分隔字符串使同种字符出现在一起

763. 划分字母区间

class Solution {
public List<Integer> partitionLabels(String S) {
int[] last = new int[26];
for (int i = 0; i < S.length(); ++i)
last[S.charAt(i) - 'a'] = i; int j = 0, anchor = 0;
List<Integer> ans = new ArrayList();
for (int i = 0; i < S.length(); ++i) {
j = Math.max(j, last[S.charAt(i) - 'a']);
if (i == j) {
ans.add(i - anchor + 1);
anchor = i + 1;
}
}
return ans;
}
}

Leedcode算法专题训练(贪心)的更多相关文章

  1. Leedcode算法专题训练(搜索)

    BFS 广度优先搜索一层一层地进行遍历,每层遍历都是以上一层遍历的结果作为起点,遍历一个距离能访问到的所有节点.需要注意的是,遍历过的节点不能再次被遍历. 第一层: 0 -> {6,2,1,5} ...

  2. Leedcode算法专题训练(分治法)

    归并排序就是一个用分治法的经典例子,这里我用它来举例描述一下上面的步骤: 1.归并排序首先把原问题拆分成2个规模更小的子问题. 2.递归地求解子问题,当子问题规模足够小时,可以一下子解决它.在这个例子 ...

  3. Leedcode算法专题训练(二分查找)

    二分查找实现 非常详细的解释,简单但是细节很重要 https://www.cnblogs.com/kyoner/p/11080078.html 正常实现 Input : [1,2,3,4,5] key ...

  4. Leedcode算法专题训练(排序)

    排序 快速排序 用于求解 Kth Element 问题,也就是第 K 个元素的问题. 可以使用快速排序的 partition() 进行实现.需要先打乱数组,否则最坏情况下时间复杂度为 O(N2). 堆 ...

  5. Leedcode算法专题训练(双指针)

    算法思想 双指针 167. 两数之和 II - 输入有序数组 双指针的典型用法 如果两个指针指向元素的和 sum == target,那么得到要求的结果: 如果 sum > target,移动较 ...

  6. Leedcode算法专题训练(位运算)

    https://www.cnblogs.com/findbetterme/p/10787118.html 看这个就完事了 1. 统计两个数的二进制表示有多少位不同 461. Hamming Dista ...

  7. Leedcode算法专题训练(数组与矩阵)

    1. 把数组中的 0 移到末尾 283. Move Zeroes (Easy) Leetcode / 力扣 class Solution { public void moveZeroes(int[] ...

  8. Leedcode算法专题训练(数学)

    204. 计数质数 难度简单523 统计所有小于非负整数 n 的质数的数量. class Solution { public int countPrimes(int n) { boolean[] is ...

  9. Leedcode算法专题训练(字符串)

    4. 两个字符串包含的字符是否完全相同 242. Valid Anagram (Easy) Leetcode / 力扣 可以用 HashMap 来映射字符与出现次数,然后比较两个字符串出现的字符数量是 ...

随机推荐

  1. 「NGK每日快讯」12.30日NGK第57期官方快讯!

  2. MySQL修改表中字段的字符集

    MySQL修改表中字段的字符集 ALTER TABLE 表名 MODIFY 字段名 要修改的属性: 例:ALTER TABLE `guaduates` MODIFY `studentno` CHAR( ...

  3. Egg.js 是什么?

    Egg.js 是什么? 阿里巴巴出 Egg.js 为企业级框架和应用而生,我们希望由 Egg.js 孕育出更多上层框架,帮助开发团队和开发人员降低开发和维护成本. 注:Egg.js 缩写为 Egg 设 ...

  4. JS常用数值验证

    1.正整数验证 正整数是大于0的整数. function validateInteger(val) { return Number.isInteger(val) && val > ...

  5. css3自动换行排列

    如果一行放不下就会自动换行 display: flex; flex-wrap: wrap; 示例 : html <div class="container"> < ...

  6. .Net Core 3.1浏览器后端服务(四) 你眼中的依赖注入与我相同吗?

    一.前言 DI-Dependency Injection 依赖注入 IoC-Inversion of Control 控制反转 近几年这依赖注入. 控制反转已成为软件开发中不可或缺的一部分,那么该怎么 ...

  7. POJ-1458(LCS:最长公共子序列模板题)

    Common Subsequence POJ-1458 //最长公共子序列问题 #include<iostream> #include<algorithm> #include& ...

  8. Python数据格式:%s字符串,%d整型,%f浮点型

    格式化符% name="Tom" age=int(input("age")) pt2="%s你的年龄是%d"%(name,age) prin ...

  9. struct2中package的参数解析

    struct2框架的核心组件是action和拦截器,它使用包来管理action和拦截器,每个包就是多个action.多个拦截器引用的集合.在struct.xml中,package元素用于定义包的配置, ...

  10. nginx使用-2(模块和日志)

    默认官方模块 1.1.Gzip压缩 压缩文件,使文件变小,传输更快了.目前市场上大部分浏览器是支持GZIP的.IE6以下支持不好,会出现乱码情况. 官方文档:http://nginx.org/en/d ...