算法训练营第二十三天 | 贪心算法(一)

文章目录

  • 一、贪心算法理论基础
  • 二、Leetcode 455.分发饼干
  • 二、Leetcode 376. 摆动序列
  • 三、Leetcode 53. 最大子序和


一、贪心算法理论基础

贪心算法是一种在每一步选择中都采取当前状态下的最优决策,从而希望最终达到全局最优解的算法设计技术。

基本思想

  • 贪心算法总是做出在当前看来是最优的选择,也就是说,它不从整体最优上加以考虑,所做出的仅仅是在某种意义上的局部最优解。它通常以自顶向下的方式进行,每一步都选择一个局部最优解,逐步构造出问题的解。

使用条件

  • 贪心选择性质:问题的整体最优解可以通过一系列局部最优的选择来达到。即每一步的最优选择最终能导致全局的最优解。
  • 最优子结构性质:问题的最优解包含了子问题的最优解。也就是说,原问题的最优解可以由子问题的最优解组合而成。

一般解题步骤

  1. 将问题分解为若干个子问题
  2. 找出适合的贪心策略
  3. 求解每一个子问题的最优解
  4. 将局部最优解堆叠成全局最优解

二、Leetcode 455.分发饼干

假设你是一位很棒的家长,想要给你的孩子们一些小饼干。但是,每个孩子最多只能给一块饼干。

对每个孩子 i,都有一个胃口值 g[i],这是能让孩子们满足胃口的饼干的最小尺寸;并且每块饼干 j,都有一个尺寸 s[j] 。如果 s[j] >= g[i],我们可以将这个饼干 j 分配给孩子 i ,这个孩子会得到满足。你的目标是满足尽可能多的孩子,并输出这个最大数值。

示例:

输入: g = [1,2,3], s = [1,1]
输出: 1
解释: 
你有三个孩子和两块小饼干,3 个孩子的胃口值分别是:1,2,3。
虽然你有两块小饼干,由于他们的尺寸都是 1,你只能让胃口值是 1 的孩子满足。
所以你应该输出 1

引用:

原文链接:https://programmercarl.com/0455.%E5%88%86%E5%8F%91%E9%A5%BC%E5%B9%B2.html#%E7%AE%97%E6%B3%95%E5%85%AC%E5%BC%80%E8%AF%BE
题目链接:https://leetcode.cn/problems/assign-cookies/description/
视频讲解:https://www.bilibili.com/video/BV1MM411b7cq/

为了满足更多的小孩,就不要造成饼干尺寸的浪费。

大尺寸的饼干既可以满足胃口大的孩子也可以满足胃口小的孩子,那么就应该优先满足胃口大的。

这里的局部最优就是大饼干喂给胃口大的,充分利用饼干尺寸喂饱一个,全局最优就是喂饱尽可能多的小孩。

要更多的节省饼干,所以每个小孩分到的饼干够用就行。

先将两个数组进行排序,然后利用双指针算法,每个孩子选择最小且够吃的饼干。

代码:

class Solution:def findContentChildren(self, g: List[int], s: List[int]) -> int:count = 0s.sort()g.sort()i = 0j = 0while i<len(g) and j<len(s):if s[j] >= g[i]:j += 1i += 1count += 1else:j += 1return count

二、Leetcode 376. 摆动序列

如果连续数字之间的差严格地在正数和负数之间交替,则数字序列称为 摆动序列 。第一个差(如果存在的话)可能是正数或负数。仅有一个元素或者含两个不等元素的序列也视作摆动序列。

例如, [1, 7, 4, 9, 2, 5] 是一个 摆动序列 ,因为差值 (6, -3, 5, -7, 3) 是正负交替出现的。

相反,[1, 4, 7, 2, 5][1, 7, 4, 5, 5] 不是摆动序列,第一个序列是因为它的前两个差值都是正数,第二个序列是因为它的最后一个差值为零。
子序列可以通过从原始序列中删除一些(也可以不删除)元素来获得,剩下的元素保持其原始顺序。

给你一个整数数组 nums ,返回 nums 中作为 摆动序列 的 最长子序列的长度 。

示例:

输入:nums = [1,7,4,9,2,5]
输出:6
解释:整个序列均为摆动序列,各元素之间的差值为 (6, -3, 5, -7, 3)

引用:

原文链接:https://programmercarl.com/0376.%E6%91%86%E5%8A%A8%E5%BA%8F%E5%88%97.html
题目链接:https://leetcode.cn/problems/wiggle-subsequence/description/
视频讲解:https://www.bilibili.com/video/BV17M411b7NS/

源自代码随想录

我们借用一下代码随想录给出的图片,这样就很好理解我们都需要做什么事情。

图中给出要删除非摆动的点,其实只是方便我们理解。我们在实际操作中并不需要去复杂的删除点,只需要记录一下摆动点的数量即可。

我们定义两个变量 preddiff==num[i]-nums[i-1]curdiff=nums[i+1]-nums[i],用来记录某个点左右的变化值,所以我们的终止条件就可以写为如下形式

if (prediff>0 and curdiff<0) or (prediff<0 and curdiff>0):result += 1

在此基础上,我们还有三个需要注意的细节。

上下坡中有平路
源自代码随想录
在这里最后一个 2,我们的 prediff 值等于零, curdiff 小于零,这种情况我们也算是一种摆动,所以我们也需要记录一下。我们就需要完善一下终止条件:

if (prediff>=0 and curdiff<0) or (prediff<=0 and curdiff>0):result += 1

首尾值
当数组只有两个值的时候,我们这种判断条件需要三个值,会发生 IndexError

我们可以在数组开头前面默认多加一个平路(并不是真正的去添加一个元素),并设置 prediff 的初始值就为零,这样上面的判断条件完全可以涵盖这种情况。

对于最后一个元素,根据题目描述它是一定会形成一个摆动的,所以我们在循环的时候就不遍历最后一个元素,并且设置初始结果的值为 1

result = 1
prediff = 0
for i in range(len(nums)-1):pass

单调坡中有平路
源自代码随想录
由图中可以看出,第一个 2 和最后一个 2 都是符合我们记录摆动值的条件,最后摆动的结果是 3,但是我们实际的摆动结果是 2

我们在记录 prediff 的值的时候并不是直接使用 nums[i]-nums[i-1] 进行赋值,而是不断的去跟踪 curdiff 的值。

我们只需要在这个坡度摆动变化的时候,更新 prediff 就行,这样 prediff 在 单调区间有平坡的时候就不会发生变化,造成我们的误判。

代码:

class Solution:def wiggleMaxLength(self, nums: List[int]) -> int:result = 1prediff = 0curdiff = 0if len(nums) == 1:return resultfor i in range(len(nums)-1):curdiff = nums[i+1] - nums[i]if (prediff<=0 and curdiff>0) or (prediff>=0 and curdiff<0):result += 1prediff = curdiffreturn result

三、Leetcode 53. 最大子序和

给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

子数组是数组中的一个连续部分。

示例:

输入:nums = [-2,1,-3,4,-1,2,1,-5,4]
输出:6
解释:连续子数组 [4,-1,2,1] 的和最大,为 6

引用:

原文链接:https://programmercarl.com/0053.%E6%9C%80%E5%A4%A7%E5%AD%90%E5%BA%8F%E5%92%8C.html
题目链接:https://leetcode.cn/problems/maximum-subarray/description/
视频讲解:https://www.bilibili.com/video/BV1aY4y1Z7ya/

暴力美学:使用两层 for 循环,外层遍历子数组的起始位置,内层循环来控制子数组的长度,最后将最大值的结果保存即可。暴力法的时间复杂度为 O(n^2),超时。

贪心思想:这题的贪心思想在于,当我们的连续和为负数时,它对后续的和起到的是副作用(越加越小),所以我们直接抛弃这段子数组,从新的结点开始。

我们使用 result 保存最大连续和的时候,这个操作一定要在判断连续和是否小于零的前面,因为最大和也有可能是负数。

代码:

class Solution:def maxSubArray(self, nums):# 暴力法result = float('-inf')  # 初始化结果为负无穷大count = 0for i in range(len(nums)):  # 设置起始位置count = 0for j in range(i, len(nums)):  # 从起始位置i开始遍历寻找最大值count += nums[j]result = max(count, result)  # 更新最大值return result# 贪心算法result = float('-inf')count = 0for i in range(len(nums)):count += nums[i]result = max(count, result)if count <= 0:count = 0return result

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/75566.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

css基础-display 常用布局

CSS display 属性详解 属性设置元素是否被视为块级或行级盒子以及用于子元素的布局&#xff0c;例如流式布局、网格布局或弹性布局。 一、基础显示模式 1. block 作用&#xff1a; 元素独占一行可设置宽高和内外边距默认宽度撑满父容器 应用场景&#xff1a; 布局容器&a…

速卖通API数据清洗实战:从原始JSON到结构化商品数据库

下面将详细介绍如何把速卖通 API 返回的原始 JSON 数据清洗并转换为结构化商品数据库。 1. 数据获取 首先要借助速卖通 API 获取商品数据&#xff0c;以 Python 为例&#xff0c;可使用requests库发送请求并得到 JSON 数据。 import requests# 替换为你的 API Key 和 Secret …

【零基础入门unity游戏开发——2D篇】2D物理系统 —— 2D刚体组件(Rigidbody2D)

考虑到每个人基础可能不一样,且并不是所有人都有同时做2D、3D开发的需求,所以我把 【零基础入门unity游戏开发】 分为成了C#篇、unity通用篇、unity3D篇、unity2D篇。 【C#篇】:主要讲解C#的基础语法,包括变量、数据类型、运算符、流程控制、面向对象等,适合没有编程基础的…

Collectors.toMap / list 转 map

前言 略 Collectors.toMap List<User> userList ...; Map<Long, User> userMap userList.stream().collect(Collectors.toMap(User::getUserId, Function.identity()));假如id存在重复值&#xff0c;则会报错Duplicate key xxx, 解决方案 两个重复id中&#…

热门面试题第13天|Leetcode 110.平衡二叉树 257. 二叉树的所有路径 404.左叶子之和 222.完全二叉树的节点个数

222.完全二叉树的节点个数&#xff08;优先掌握递归&#xff09; 需要了解&#xff0c;普通二叉树 怎么求&#xff0c;完全二叉树又怎么求 题目链接/文章讲解/视频讲解&#xff1a;https://programmercarl.com/0222.%E5%AE%8C%E5%85%A8%E4%BA%8C%E5%8F%89%E6%A0%91%E7%9A%84%E8…

关于Object.assign

Object.assign 基本用法 Object.assign() 方法用于将所有可枚举属性的值从一个或者多个源对象source复制到目标对象。它将返回目标对象target const target { a: 1, b: 2 } const source { b: 4, c: 5 }const returnedTarget Object.assign(target, source)target // { a…

GitHub高级筛选小白使用手册

GitHub高级筛选小白使用手册 GitHub 提供了强大的搜索功能&#xff0c;允许用户通过高级筛选器来精确查找仓库、Issues、Pull Requests、代码等。下面是一些常用的高级筛选用法&#xff0c;帮助你更高效地使用 GitHub 搜索功能。 目录 搜索仓库搜索Issues搜索Pull Requests搜…

手动集成sqlite的方法

注意到sqlite有backup方法&#xff08;https://www.sqlite.org/backup.html&#xff09;。 也注意到android中sysroot下&#xff0c;没有sqlite3的库&#xff0c;也没有相关头文件。 如果要使用 sqlite 的backup&#xff0c;那么就需要手动集成sqlite代码到项目中。可以如下操…

蓝桥杯真题 2109.统计子矩阵

原题地址:1.统计子矩阵 - 蓝桥云课 问题描述 给定一个 NMNM 的矩阵 AA, 请你统计有多少个子矩阵 (最小 1111, 最大 NM)NM) 满足子矩阵中所有数的和不超过给定的整数 KK ? 输入格式 第一行包含三个整数 N,MN,M 和 KK. 之后 NN 行每行包含 MM 个整数, 代表矩阵 AA. 输出格…

蓝桥杯—最少操作数

一.题目 分析:每次可以进行三次操作&#xff0c;求在n步操作后可以达到目标数的最小n&#xff0c;和最短路径问题相似&#xff0c;分层遍历加记忆化搜索防止时间复杂度过高&#xff0c;还需要减枝操作 import java.util.HashSet; import java.util.LinkedList; import java.ut…

Linux内核NIC网卡驱动实战案例分析

以下Linux 内核模块实现了一个虚拟网络设备驱动程序&#xff0c;其作用和意义如下&#xff1a; 1. 作用 &#xff08;1&#xff09;创建虚拟网络设备对 驱动程序动态创建了两个虚拟网络设备&#xff08;nic_dev[0]和nic_dev[1]&#xff09;&#xff0c;模拟物理网卡的功能。这两…

Trae初使用心得(Java后端)

1.前提 2025年3月3日&#xff0c;字节跳动正式官宣“中国首个 AI 原生集成开发环境&#xff08;AI IDE&#xff09;”Trae 国内版正式上线&#xff0c;由于之前项目的原因小编没有及时的去体验&#xff0c;这几日专门抽空去体验了一下感觉还算可以。 2.特点 Trade重在可以白嫖…

[项目]基于FreeRTOS的STM32四轴飞行器: 十二.角速度加速度滤波

基于FreeRTOS的STM32四轴飞行器: 十二.滤波 一.滤波介绍二.对角速度进行一阶低通滤波三.对加速度进行卡尔曼滤波 一.滤波介绍 模拟信号滤波&#xff1a; 最常用的滤波方法可以在信号和地之间并联一个电容&#xff0c;因为电容通交隔直&#xff0c;信号突变会给电容充电&#x…

UNIX网络编程笔记:TCP、UDP、SCTP编程的区别

一、核心特性对比 特性TCPUDPSCTP连接方式面向连接&#xff08;三次握手&#xff09;无连接面向连接&#xff08;四次握手&#xff09;可靠性可靠传输&#xff08;重传、确认机制&#xff09;不可靠传输可靠传输&#xff08;多路径冗余&#xff09;传输单位字节流&#xff08;…

Python爬虫异常处理:自动跳过无效URL

爬虫在运行过程中常常会遇到各种异常情况&#xff0c;其中无效URL的出现是较为常见的问题之一。无效URL可能导致爬虫程序崩溃或陷入无限等待状态&#xff0c;严重影响爬虫的稳定性和效率。因此&#xff0c;掌握如何在Python爬虫中自动跳过无效URL的异常处理技巧&#xff0c;对于…

C++语法学习的主要内容

科技特长生方向&#xff0c;主要学习的内容为 一&#xff0c;《C语法》 二&#xff0c;《数据结构》 三&#xff0c;《算法》 四&#xff0c;《计算机基础知识》 五&#xff0c;《初高中的数学知识》 其中&#xff0c;《C语法》学习的主要内容如下: 1,cout输出语句和键盘…

3、孪生网络/连体网络(Siamese Network)

目的: 用Siamese Network (孪生网络) 解决Few-shot learning (小样本学习)。 Siamese Network并不是Meta Learning最好的方法, 但是通过学习Siamese Network,非常有助于理解其他Meta Learning算法。 这里介绍了两种方法:Siamese Network (孪生网络)、Trplet Loss Siam…

从零构建大语言模型全栈开发指南:第二部分:模型架构设计与实现-2.2.1从零编写类GPT-2模型架构(规划模块与代码组织)

👉 点击关注不迷路 👉 点击关注不迷路 👉 点击关注不迷路 文章大纲 2.2.1 从零编写类GPT-2模型架构(规划模块与代码组织)1. 模型架构设计规划1.1 架构核心组件2. 模块化设计实现2.1 输入处理模块2.1.1 分词与嵌入2.1.2 位置编码2.2 解码块设计2.2.1 多头注意力子层2.2.…

消息队列(Kafka及RocketMQ等对比联系)

目录 消息队列 一、为什么使用消息队列&#xff1f;消息队列有什么优点/缺点&#xff1f;介绍下Kafka、ActiveMQ、RabbitMQ、RocketMQ有什么优点缺点&#xff0c;如何取舍&#xff1f; 1.公司业务场景是什么&#xff0c;这个业务场景有什么挑战&#xff0c;如果不用MQ有什么麻…

Android 13系统定制实战:基于系统属性的音量键动态屏蔽方案解析

1. 需求背景与实现原理 在Android 13系统定制化开发中&#xff0c;需根据设备场景动态屏蔽音量键&#xff08;VOLUME_UP/VOLUME_DOWN&#xff09;功能。其核心诉求是通过系统属性&#xff08;persist.sys.roco.volumekey.enable&#xff09;控制音量键的响应逻辑&#xff0c;确…