LeetCode刷题日记之贪心算法(一)

news2024/10/19 6:27:15

目录

  • 前言
  • 分发饼干
  • 摆动序列
  • 最大子数组和
  • 总结


前言

作为LeetCode刷题的过程中,贪心算法一直是一个经典的算法思路。在这篇文章中,我将记录自己刷LeetCode贪心算法题的过程,并逐步梳理该算法的核心逻辑,包括如何选择最优解、判断局部最优选择的可行性、如何更新问题状态等。希望通过这一系列的学习记录,能够帮助我进一步掌握贪心算法的精髓,也能给其他正在刷题的小伙伴提供一些参考和思路✍✍✍


分发饼干

LeetCode题目链接

这道题目就是你有一个饼干数组,里面表示你有几块不同大小的饼干,然后呢有一个小孩数组,表示有几个不同胃口大小的小孩,你要分配饼干尽可能让最多的孩子得到满足,然后输出得到满足的孩子数量🤔🤔🤔

请添加图片描述

我们来思路梳理

  • 首先将孩子的胃口值数组 g 和饼干的尺寸数组 s 进行升序排序。从胃口最小的孩子开始,用最小尺寸的饼干去满足。这样可以最大化地利用较小的饼干,避免浪费大饼干🤔🤔🤔(小饼干满足小胃口)
  • 先将孩子的胃口和饼干尺寸排序。从胃口最大的孩子开始,用尽可能大的饼干去满足。这样可以保证较大的饼干不浪费在小胃口的孩子上🤔🤔🤔(大饼干满足大胃口)

这里我们就以第一种策略为例来分析贪心的四个子逻辑

  • 如何判断最优解

    • 最优解的目标是尽可能多地满足孩子的胃口🤔🤔🤔为了达到这个目标,选择一种贪心策略来匹配饼干和孩子的胃口。通过排序和逐一分配饼干,可以确保每次都能做出最优选择——满足当前最小的胃口
  • 判断局部最优选择的可行性

    • 局部最优选择是尽量用最小的饼干去满足胃口最小的孩子🤔🤔🤔这样我们不会浪费大尺寸的饼干,可以为更大胃口的孩子保留大尺寸的饼干
  • 更新问题状态

    • 每当分配一个饼干给孩子时,我们需要移除已分配的饼干,表示该饼干已经用过🤔🤔🤔移除已满足的孩子,表示该孩子已经满足胃口🤔🤔🤔接着处理下一个未满足的孩子和未使用的饼干
  • 重复选择

    • 不断重复上述过程,直到饼干或孩子处理完毕。每次都选择最小的饼干去匹配最小的胃口,保证每次都是局部最优解🤔🤔🤔

贪心算法完整代码如下

class Solution {
    public int findContentChildren(int[] g, int[] s) {
        //将胃口数组和饼干尺寸数组进行升序排序
        Arrays.sort(g);
        Arrays.sort(s);
        //初始化遍历孩子数组和饼干数组的索引
        int childIndex = 0;
        int cookieIndex = 0;

        //重复选择:当还有未处理的孩子和饼干时进行分配
        while(childIndex < g.length && cookieIndex < s.length){
            //判断局部最优选择的可行性
            if(s[cookieIndex] >= g[childIndex])childIndex++;//更新问题状态
            cookieIndex++;//更新问题状态
        }
        return childIndex;//最优解即是被满足孩子的数量
    }
}

摆动序列

LeetCode题目链接

这道题就是要返回一个整数数组nums中最长摆动序列的长度,什么是摆动序列呢?就是像[1,7,4,9,2,5]这种连续数字之间的差在正数与负数之间交替[6,-3,5,-7,3],另外的就是只有一个元素或者是两个不等元素的序列也可以视作摆动序列🤔🤔🤔

请添加图片描述

我们来进行思路梳理

  • 摆动序列从第一个元素开始,在遍历过程中,计算当前元素与前一个元素的差值。如果这个差值与前一个差值的符号相反(正负交替),则这个元素就是摆动序列中的一个关键点,计入摆动序列🤔如果连续的差值符号相同(即一直增加或一直减少),则忽略中间的元素,只保留转折点🤔如果数组中只有一个元素或者两个不相等的元素,也视为摆动序列🤔

我们来梳理贪心算法的四个子逻辑

  • 如何判断最优解
    • 最优解的目标是找到最长的摆动序列,也就是每当差值出现正负交替时,我们就保留当前元素作为摆动序列的一部分。因此,最优解是通过选择能够引发“转折”的元素,构建一个最长的交替变化的子序列🤔🤔🤔
  • 判断局部最优选择的可行性
    • 局部最优选择是:每次遇到符号发生改变时,保留该元素,这意味着当前元素的差值与之前的差值是正负交替的🤔🤔🤔
  • 更新问题状态
    • 每次选择一个摆动的转折点后,更新当前的符号变化状态(上升还是下降),移动到下一个元素,继续判断它是否符合转折点的条件🤔🤔🤔
  • 重复选择
    • 我们从第一个元素开始遍历数组,并每次遇到符号变化时,将其纳入子序列。不断重复这个过程直到遍历完数组🤔🤔🤔

梳理完逻辑已经很清楚了,贪心算法完整代码如下

class Solution {
    public int wiggleMaxLength(int[] nums) {
        //特殊情况
        if(nums.length < 2) return nums.length;

        int count = 1;//摇摆序列计数器
        int prevDiff = 0;//上一个元素的差值初始为0

        for(int i = 1; i < nums.length; i++){//遍历数组找摇摆序列
            int diff = nums[i] - nums[i - 1];//计算当前元素和前一个元素的差值

            //判断局部最优选择的可行性
            if((diff > 0 && prevDiff <= 0) || (diff < 0 && prevDiff >= 0)){
                count++;//摇摆序列长度加一
                prevDiff = diff;//更新差值
            }
        }
        return count;//返回摇摆序列的长度
    }
}

最大子数组和

LeetCode题目链接

这道题和上一道题不同的是,这里是给一个整数数组,要找一个具有最大和的连续子数组(最少包含一个元素)并返回这个最大和🤔🤔🤔

请添加图片描述

我们来思路梳理

  • 在遍历数组时,维护当前的子数组和。如果当前子数组的和为负数,意味着它对后续的元素没有增益效果,因此应舍弃当前子数组,从下一个元素重新开始计算子数组和🤔在遍历过程中,不断更新全局的最大子数组和。如果当前子数组的和大于之前记录的全局最大和,则更新全局最大和🤔

我们来进一步梳理贪心算法的四个子逻辑

  • 如何判断最优解
    • 最优解是找到具有最大和的连续子数组。在遍历过程中,我们需要找到一种贪心策略:选择当前的元素并判断是继续加到当前的子数组中,还是从当前元素重新开始一个新的子数组🤔🤔🤔
  • 判断局部最优选择的可行性
    • 局部最优选择是:当前子数组和如果为负数,就放弃之前的子数组,从当前元素重新开始新的子数组。如果当前子数组和为正,就继续把当前元素加入到子数组中。这样可以确保每一步都选择对未来最有利的子数组🤔🤔🤔
  • 更新问题状态
    • 每次计算当前子数组和时,更新全局最大和 maxSum,并在每一步更新当前子数组和 currSum,判断是否重新开始子数组🤔🤔🤔
  • 重复选择
    • 重复遍历数组中的每个元素,并在每一步更新 currSummaxSum,直到遍历完整个数组🤔🤔🤔

梳理完逻辑我们直接上代码

class Solution {
    public int maxSubArray(int[] nums) {
        int maxSum = nums[0]; //全局最优解初始化
        int currentSum = nums[0]; //当前子数组和

        for(int i = 1; i < nums.length; i++){
            currentSum = Math.max(nums[i], currentSum + nums[i]);//判断局部最优选择的可行性
            maxSum = Math.max(currentSum, maxSum);//更新问题状态
        }
        return maxSum;//返回全局最优解
    }
}

说了一大堆巴拉巴拉,代码就几行🤪🤪🤪


总结

今天的贪心算法第一轮学习的第一天一些逻辑上面的东西可能说的有点多,后续的话将减少不必要的逻辑阐述,我们专注于问题代码的核心逻辑,大家一起加油,奥利给✊✊✊

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

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

相关文章

PS证件照换底色

ps工具&#xff1a;Adobe Photoshop 2021 文章目录 1. 扣取人物2. 更换底色 1. 扣取人物 2. 更换底色

SpringSecurity使用介绍

1、SpringSecurity 1.1 SpringSecurity简介 Spring Security是基于Spring的安全框架,提供了包含认证和授权的落地方案&#xff1b;Spring Security底层充分利用了Spring IOC和AOP功能&#xff0c;为企业应用系统提供了声明式安全访问控制解决方案&#xff1b;SpringSecurity可…

数据字典是什么?和数据库、数据仓库有什么关系?

一、数据字典的定义及作用 数据字典是一种对数据的定义和描述的集合&#xff0c;它包含了数据的名称、类型、长度、取值范围、业务含义、数据来源等详细信息。 数据字典的主要作用如下&#xff1a; 1. 对于数据开发者来说&#xff0c;数据字典包含了关于数据结构和内容的清晰…

3. 单例模式唯一性问题—构造函数

1. 构造函数带来的唯一性问题指什么&#xff1f; 对于不继承MonoBehaviour的单例模式基类 我们要避免在外部 new 单例模式类对象 例如 &#xff08;完整单例模式定义在上一节&#xff09; public class Main : MonoBehaviour {void Start(){// 破坏单例模式的唯一性&#xf…

跨越距离:2024四大远程控制软件体验!

在多元化的现代生活中&#xff0c;远程控制软件已经成为我们不可或缺的助手。它们可以帮助我们实现远程办公、远程协助、远程游戏等多种功能。今天&#xff0c;我们就来为大家盘点几款热门的远程控制软件&#xff0c;包括向日葵远程控制、RayLink远程控制、Parsec和AirDroid&am…

C++笔记之静态多态和动态多态

C++笔记之静态多态和动态多态 code review! 在C++中,多态(Polymorphism)是面向对象编程的一个核心概念,允许对象以多种形式存在。多态性主要分为静态多态(Static Polymorphism)和动态多态(Dynamic Polymorphism)。下面将详细解释这两种多态及其在C++中的实现方式、优缺…

Stable Diffusion Web UI 大白话术语解释 (二)

归纳整理&#xff0c;Stable Diffusion Web UI 使用过程中&#xff0c;相关术语 ControlNet ControlNet 说简单点&#xff0c;就是你可以给 AI 一些“规则”&#xff0c;比如让它根据某些线条、结构或者骨架去画图。 这样能让 AI 画出更符合你要求的图片&#xff0c;特别适合画…

QT 实现按钮多样化

1.界面实现效果 以下是具体的项目需要用到的效果展示&#xff0c;可以根据需要&#xff0c;实例化想要的按钮。 2.简介 原理&#xff1a;使用Qt的QPropertyAnimation动画类&#xff0c;这里简单来说就是切换两个按钮样式。 请看以下结构体&#xff1a; #define MAX_LINE_C…

为什么Java中1==1为真,而128==128为假?基于享元模式的整数缓存原理分析

❃博主首页 &#xff1a; 「码到三十五」 &#xff0c;同名公众号 :「码到三十五」&#xff0c;wx号 : 「liwu0213」 ☠博主专栏 &#xff1a; <mysql高手> <elasticsearch高手> <源码解读> <java核心> <面试攻关> ♝博主的话 &#xff1a…

从零开始搭建你的DolphinScheduler分布式任务调度平台实战指南

文章目录 前言1. 安装部署DolphinScheduler1.1 启动服务 2. 登录DolphinScheduler界面3. 安装内网穿透工具4. 配置Dolphin Scheduler公网地址5. 固定DolphinScheduler公网地址 前言 本篇教程和大家分享一下DolphinScheduler的安装部署及如何实现公网远程访问&#xff0c;结合内…

React速成

useRef获取DOM 组件通讯 子传父 function Son({ onGetMsg }){const sonMsg this is son msgreturn (<div>{/* 在子组件中执行父组件传递过来的函数 */}<button onClick{()>onGetMsg(sonMsg)}>send</button></div>) }function App(){const getMsg…

厨房老鼠数据集:掀起餐饮卫生监测的科技浪潮

厨房老鼠数据集&#xff1a;掀起餐饮卫生监测的科技浪潮 摘要&#xff1a;本文深入探讨了厨房老鼠数据集在餐饮行业卫生管理中的重要性及其相关技术应用。厨房老鼠数据集通过收集夜间厨房图像、老鼠标注信息以及环境数据&#xff0c;为深度学习模型提供了丰富的训练样本。基于…

两个案例全面阐述全链路测试怎么做

首先我们先针对全链路功能测试部分进行一下讲解。去年的时候&#xff0c;有一家电商公司可能知道我一直在帮银行做相关的测试&#xff0c;就请我帮他们去做一些规划。这个平台有虚拟订单&#xff0c;也有实体订单&#xff0c;方式不太一样。 还涉及到分账分佣以及跟银行的对接…

基于SpringBoot+Vue+uniapp的涪陵区特色农产品交易系统的详细设计和实现(源码+lw+部署文档+讲解等)

详细视频演示 请联系我获取更详细的视频演示 项目运行截图 技术框架 后端采用SpringBoot框架 Spring Boot 是一个用于快速开发基于 Spring 框架的应用程序的开源框架。它采用约定大于配置的理念&#xff0c;提供了一套默认的配置&#xff0c;让开发者可以更专注于业务逻辑而不…

【IC设计】复旦微行业分析

文章目录 概述各产品线安全与识别芯片&#xff1a;非挥发存储器&#xff1a;智能电表 MCU &#xff1a;集成电路测试服务&#xff1a; 前景公司是FPGA领军企业&#xff0c;在国产替代背景下深度受益优势 1&#xff1a;公司最早推出亿门级 FPGA 产品&#xff0c;提前卡位 28nm 赛…

python的多线程和多进程

首先需要明确的是&#xff0c;多进程和其他语言的一样&#xff0c;能够利用多核cpu&#xff0c;但是python由于GIL的存在&#xff0c;多线程在执行的时候&#xff0c;实际上&#xff0c;每一时刻只有一个线程在执行。相当于是单线程。然而多线程在某些情况下&#xff0c;还是能…

爬虫逆向-js进阶

1.作用域和闭包 //作用域 // var a 3 // // function test(a){ // var a 1; // console.log(函数内部,a) // } // test(2) // // console.log(a)//闭包 // function jiami(){ // function encrypt(){ // console.log(在这里进行加密了) // } // p…

GaussDB高智能--自治运维技术(中)

目录 2.4 日志分析 &#xff08;1&#xff09;日志解析阶段 &#xff08;2&#xff09;日志分析模型的训练 &#xff08;3&#xff09;在线检测模块 2.5 慢SQL发现 &#xff08;1&#xff09;训练阶段 &#xff08;2&#xff09;预测流程 2.6 慢SQL诊断 &#x…

只想简单跑个 AI 大模型,却发现并不简单

之前我用 Ollama 在本地跑大语言模型&#xff08;可以参考《AI LLM 利器 Ollama 架构和对话处理流程解析》&#xff09;。这次想再捣鼓点进阶操作&#xff0c;比如 fine-tuning。 我的想法是&#xff1a;既然有现成的大模型&#xff0c;为什么不自己整理些特定领域的数据集&am…

如何捕捉行情爆发的前兆

在金融市场的激烈角逐中&#xff0c;每一次行情的爆发都是投资者获取丰厚回报的关键时刻。然而&#xff0c;如何识别并把握这些时刻&#xff0c;却是一门需要深厚金融专业知识和敏锐洞察力的艺术。今天&#xff0c;我们就来深入探讨行情爆发的初期信号&#xff0c;揭示那些能够…