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. VOR/DME程序进近、复飞保护区的绘制

    今天尝试画一个典型的VOR/DME进近程序保护区. 读图 某机场VOR/DME进近程序平面图部分如下图所示:   该程序剖面图部分如下图所示:   分析 该机场采用了偏置导航台布局(导航台在机场内), ...

  2. java中的桥接方法

    本文转载自java中什么是bridge method(桥接方法) 导语 在看spring-mvc的源码的时候,看到在解析handler方法时,有关于获取桥接方法代码,不明白什么是桥接方法,经过查找资料 ...

  3. 线上CPU飙升100%问题排查

    本文转载自线上CPU飙升100%问题排查 引子 对于互联网公司,线上CPU飙升的问题很常见(例如某个活动开始,流量突然飙升时),按照本文的步骤排查,基本1分钟即可搞定!特此整理排查方法一篇,供大家参考 ...

  4. 微信小程序:数组拼接

    一开始用concat进行拼接,总是不行,代码如下: handleItemChange(e){ console.log(e) var itemList = e.detail.value itemList ...

  5. RocketMQ基础概念剖析,并分析一下Producer的底层源码

    由于篇幅原因,本次的源码分析只限于Producer侧的发送消息的核心逻辑,我会通过流程图.代码注释.文字讲解的方式来对源码进行解释,后续应该会专门开几篇文章来做源码分析. 这篇博客聊聊关于Rocket ...

  6. Go语言学习:01-基本语法

    目录 基本语法 源文件构成 数据类型 基本类型变量 数组 切片 创建切片 调整容量 字符串与切片 常量 String Map 控制 条件语句 if switch 循环语句 函数 函数定义 函数变量 闭 ...

  7. es6 快速入门 —— 函数

    其他章节请看: es6 快速入门 系列 函数 函数是所有编程语言的重要组成部分,es6之前函数语法一直没什么变化,遗留了许多问题,javaScript开发者多年来不断抱怨,es6终于决定大力度更新函数 ...

  8. 后端程序员之路 1、linux、centos

    CentOS.Ubuntu.Debian三个linux比较异同 - 记事本 - 博客频道 - CSDN.NEThttp://blog.csdn.net/educast/article/details/ ...

  9. 腾讯一面问我SQL语句中where条件为什么写上1=1

    目录 where后面加"1=1″还是不加 不用where 1=1 在多条件查询的困惑 使用where 1=1 的好处 使用where 1=1 的坏处 where后面加"1=1″还是 ...

  10. const成员函数可以将非const指针作为返回值吗?

    先给出一段代码 class A { int *x; public: int *f() const { return x; } }; 成员函数f返回指向私有成员 x 的非常量指针,我认为这会修改成员x ...