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. 算法型稳定币USDN有哪些使用功能

    众所周知,稳定币是基于区块链的支付工具,旨在实现最终用户要求的价格稳定性.有些稳定币利用法定货币作为抵押资产.其他则使用一系列其他非法定类型的抵押资产.还有一些尝试使用算法来实现价格稳定性而根本没有抵 ...

  2. C++算法代码——Tuna

    这道题像个水题啊,可是在我做的这个OJ上就十几人做出来-- 题目来自:http://218.5.5.242:9018/JudgeOnline/problem.php?id=2084 题目描述 渔民抓住 ...

  3. JVM Attach实现原理剖析

    本文转载自JVM Attach实现原理剖析 前言 本文旨在从理论上分析JVM 在 Linux 环境下 Attach 操作的前因后果,以及 JVM 为此而设计并实现的解决方案,通过本文,我希望能够讲述清 ...

  4. Anno&Viper -分布式锁服务端怎么实现

    1.Anno简介 Anno是一个微服务框架引擎.入门简单.安全.稳定.高可用.全平台可监控.依赖第三方框架少.底层通讯RPC(Remote Procedure Call)采用稳定可靠经过无数成功项目验 ...

  5. AdoptOpenJDK是什么?

    要搞清楚AdoptOpenJDK是什么,前提条件是我们需要知道JDK是什么,OpenJDK是什么.明白了JDK和OpenJDK的关系,会容易明白什么是AdoptOpenJDK. JDK是什么? 首先, ...

  6. short i=1;i=i+1;为什么报错?

    先测试,看结果: 提示我们说不能将short类型的转化为int类型! 先不急着下结论,我们继续测试,用i+=1; 我们发现并没有报错,为什么同样是加1,会出现这样两种不同的结果呢? 查阅了一些资料,大 ...

  7. TERSUS无代码开发(笔记02)-简单实例加法

    简单实例加法 1.用户端元件(显示元件)(40个) 图标 英文名称 元件名称 使用说明 服务器端 客户端 Pane 显示块 是一个显示块,是HTML的div标签   √ Row 行 行元件中的显示元件 ...

  8. Oracle 开启或关闭归档

    开启:sqlplus / as sysdbaarchive log list;shutdown immediate;startup mount;alter database archivelog;ar ...

  9. DRF简介/接口概念

    目录 一.drf框架简介 1. drf安装 2. drf的优势 二.接口 1. 接口的概念 2. 接口文档 3. 接口规范(restful) 3.1 url链接规范 3.2 请求方式规范 3.3 响应 ...

  10. Go的包

    目录 go的包 一.包的创建规则 二.包的导入规则 三.包的函数调用 go的包 一.包的创建规则 一个包就是一个文件夹. 同一个包(文件夹)下,所有go文件都只能用同一个package,也就是每个文件 ...