DAY36:贪心算法(三)最大子数组和+买卖股票最佳时机

news2024/11/18 3:48:41

文章目录

    • 53.最大子数组和
      • 枚举思路
      • 暴力解法
      • 贪心思路
      • 完整版
      • 时间复杂度
    • 122.买卖股票的最佳时机Ⅱ(解法比较巧妙)
      • 思路
      • 完整版
      • 总结

53.最大子数组和

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

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

示例 1:

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

示例 2:

输入:nums = [1]
输出:1

示例 3:

输入:nums = [5,4,-1,7,8]
输出:23

提示:

  • 1 <= nums.length <= 10^5
  • -10^4 <= nums[i] <= 10^4

枚举思路

本题的暴力解法就是两个for循环,一个for循环遍历子数组,一个for循环用来计算当前数值对应的所有子数组的和枚举所有的和,最后返回最大值。

暴力解法

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        int result = INT_MIN;
        int sum=0;
        for(int i=0;i<nums.size();i++){
            //求所有以i为开头的子数组的和
            for(int j=i;j<nums.size();j++){
                sum += nums[j];
                result = result>sum?result:sum;
            }
            //遍历完一个数字之后重置sum
            sum=0;
        }
     return result;

    }
};

暴力解法逻辑比较简单,但是超时了

在这里插入图片描述

贪心思路

因为这个题目数组里面有负数,负数累加只会让值变得更小。因此,与其使用-2,不如重新开始,以新的位置作为连续和的起点

局部最优就是,当求解连续和为负数的时候,立刻抛弃,因为负数只会影响总和。全局最优就是找到最大子数组的和。

注意,只是连续和是负数的时候就抛弃,不是遇到负数就抛弃!因为示例可以看到,很有可能最后的结果,本来就是带有负数的

只要连续和不是负数,就往后加,因为正数对后面的数一定有增大作用。result会记录到目前为止的最大值,因此不需要担心前面的正数或者较大的总和被漏掉的情况

贪心策略如下图所示。只要连续和是负数,负数一定没有正面作用,就立刻抛弃,选择下一个位置为起点

在这里插入图片描述

完整版

  • 注意舍弃负数的情况,不需要改变for循环起始位置只需要sum置零,就算是重新开始计数了
  • 题目没有说如果数组为空,应该返回什么,所以数组为空的话返回什么都可以
class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        int result=INT_MIN;
        int sum=0;
        for(int i=0;i<nums.size();i++){
            sum+=nums[i];
            //先给result赋值,收集所有最大值防止全是负数
            result = result>sum?result:sum;
            //如果遇到负数
            if(sum<0){
                //如果<0,不需要改变for循环起始位置,直接sum赋值成0,就是从下一个重新开始计数!
                sum=0;
            }
        }
        return result;
    }
};

时间复杂度

  • 时间复杂度:O(n)
  • 空间复杂度:O(1)

122.买卖股票的最佳时机Ⅱ(解法比较巧妙)

  • 本题解法很巧妙,接触过之后要记住这种解法,即隔几天售卖的总利润每天利润累加实质上是相等的!

给你一个整数数组 prices ,其中 prices[i] 表示某支股票第 i 天的价格。

在每一天,你可以决定是否购买和/或出售股票。你在任何时候 最多 只能持有 一股 股票。你也可以先购买,然后在 同一天 出售。

返回 你能获得的 最大 利润 。

示例 1:

输入:prices = [7,1,5,3,6,4]
输出:7
解释:在第 2 天(股票价格 = 1)的时候买入,在第 3 天(股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5 - 1 = 4 。
     随后,在第 4 天(股票价格 = 3)的时候买入,在第 5 天(股票价格 = 6)的时候卖出, 这笔交易所能获得利润 = 6 - 3 = 3 。
     总利润为 4 + 3 = 7

示例 2:

输入:prices = [1,2,3,4,5]
输出:4
解释:在第 1 天(股票价格 = 1)的时候买入,在第 5 天 (股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5 - 1 = 4 。
     总利润为 4

示例 3:

输入:prices = [7,6,4,3,1]
输出:0
解释:在这种情况下, 交易无法获得正利润,所以不参与交易可以获得最大利润,最大利润为 0

提示:

  • 1 <= prices.length <= 3 * 10^4
  • 0 <= prices[i] <= 10^4

思路

本题为什么会考虑用贪心来做,就是因为任意两天的利润差值,都可以进行拆分,拆成每相邻两天利润差值的和

示例如下图所示:

在这里插入图片描述
此时,拆成了相邻两天的差值,思路就和上一道题比较类似了。

如果想要总利润变大,遇到利润为负数的时候需要立刻舍弃,然后在下一个新起点开始重新计数。我们只尝试收集正的利润。示意图如下:

在这里插入图片描述
本题的情况,任何时候只能持有一支,但是可以多次买卖,也就是说只要在所有相邻元素后-前的结果中,全部收获正数,就可以获取最大收益。

贪心策略局部最优就是遇到正数就收集,全局最优就是结果最大

完整版

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int result=0;
        int count=0;
        for(int i=0;i<prices.size()-1;i++){
            count = prices[i+1]-prices[i];
            if(count>0){
                result+=count;
            }
        }
        return result;
    }
};

总结

这道题用的是一种非常巧妙的思路,把利润分解为每天为单位的维度,而不是从 0 天到第 3 天整体去考虑。把问题转换成相邻数字的差累加最大值的问题,就很好写了。

本题中理解利润拆分是关键点! 不要整块的去看,而是把整体利润拆为每天的利润

因为1–3天整体的利润1–3天每天的利润累加,在数学上就是一个恒等式

贪心的问题就是没接触过会很难想到,接触过之后,下次遇到这种情形,就可以考虑这样的解法了。

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

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

相关文章

Java开发基础系列(一):Java设计概述

&#x1f60a; 作者&#xff1a; 一恍过去 &#x1f496; 主页&#xff1a; https://blog.csdn.net/zhuocailing3390 &#x1f38a; 社区&#xff1a; Java技术栈交流 &#x1f389; 主题&#xff1a; Java开发基础系列(一):Java设计概述 ⏱️ 创作时间&#xff1a; 2023年…

【漏洞复现】nginxWebUI 存在前台远程命令执行漏洞

文章目录 前言声明一、nginxWebUI 简介二、漏洞描述三、影响版本四、漏洞复现五、修复建议 前言 nginxWebUI 存在前台远程命令执行漏洞&#xff0c;攻击者通过该漏洞获取服务器控制权限进而进一步获取敏感数据信息。 声明 请勿利用文章内的相关技术从事非法测试&#xff0c;由…

# 文盘Rust -- FFI 浅尝

作者&#xff1a; jiashiwen 原文来源&#xff1a; https://tidb.net/blog/cfa03c39 notice"Rust is a trademark of the Mozilla Foundation in the US and other countries." rust FFI 是rust与其他语言互调的桥梁&#xff0c;通过FFI rust 可以有效继承 C 语言…

道德与社会问题简报 #4: 文生图模型中的偏见

简而言之: 我们需要更好的方法来评估文生图模型中的偏见 介绍 文本到图像 (TTI) 生成 现在非常流行&#xff0c;成千上万的 TTI 模型被上传到 Hugging Face Hub。每种模态都可能受到不同来源的偏见影响&#xff0c;这就引出了一个问题: 我们如何发现这些模型中的偏见&#xff1…

Android启动流程优化 上篇

Android启动流程优化 上篇 本文链接&#xff1a;Android启动流程优化 上篇_猎羽的博客-CSDN博客 启动流程 各个阶段图 1、各个阶段的概括总结 分为5个大阶段或者10个小阶段 【字节跳动团队】内部论坛分享也是这么处理的 补充一些只是细节点: application#onCreate()运行…

基于多案例系统学习防洪评价报告编制方法与水流数学模型建模(HECRAS、MIKE、EFDC、Delft3D、FVCOM、SWAT、SWMM等模型应用)

目录 ​专题一 《防洪评价报告编制导则解读河道管理范围内建设项目编制导则》&#xff08;SL/T808- 2021&#xff09;解读编制导则解读 专题二 防洪评价相关制度与解析 ★专题三 案例演练解析 专题四 防洪评价地形获取及常用计算实践 专题五 HEC-RAS软件原理及应用案例解析…

leetcode160.相交链表

https://leetcode.cn/problems/intersection-of-two-linked-lists/solution/ 相交链表是指两个单向链表在某个节点处相交&#xff0c;之后形成了共同的后续部分。通常&#xff0c;两个链表的长度不相等。在相交节点之前&#xff0c;两个链表的节点数可能不同&#xff0c;但在相…

Java后端编译与优化

如果我们将字节码看作是程序语言的一种中间表示形式&#xff0c;那编译器无论在何时、在何种状态下把Class文件转换成与本地基础设施相关的二进制机器码&#xff0c;它都可以视为整个编译过程的后端。 1 即时编译器 即时编译器是指运行时将热点代码编译成本地机器码&#xff…

程序员必须掌握哪些算法?——前端开发工程师需要掌握的算法

文章目录 &#x1f4cb;前言&#x1f3af;什么是算法&#xff1f;&#x1f3af;前端开发工程师需要掌握的算法&#x1f9e9;排序算法&#xff08;如快速排序、归并排序&#xff09;&#x1f9e9;搜索算法&#xff08;如二分搜索&#xff09;&#x1f9e9;图算法&#xff08;如广…

【Unity造轮子】2D横版平台跳跃游戏实现多段跳完美手感(含源码)

文章目录 前言先看效果&#xff0c;手感很丝滑原理开始1. 看到检测点的检测范围2. 二段跳实现3. 动画控制器配置 源码扩展完结 前言 随着游戏技术的不断发展&#xff0c;2D横版平台跳跃游戏成为许多玩家的最爱。这类游戏以其简单而有趣的玩法和精致的视觉效果吸引着无数游戏爱…

Kotlin~Decorator装饰器模式

概念 装饰模式指的是在不必改变原类文件和使用继承的情况下&#xff0c;动态地扩展一个对象的功能。它是通过创建一个包装对象&#xff0c;也就是装饰来包裹真实的对象。可以运行时动态添加新的功能&#xff0c;而无需改变原来的代码。 特点&#xff1a; 灵活扩展新的功能动态…

接口设计的总结

目录 前言 设计好接口的 36 个锦囊 总结 前言 作为后端开发&#xff0c;不管是什么语言&#xff0c;Java、Go 还是 C&#xff0c;其背后的后端思想都是类似的。我们做后端开发工程师&#xff0c;主要工作就是&#xff1a;如何把一个接口设计好。所以&#xff0c;今天就给大家…

北京大学考研机试题:二叉树

【题目来源】https://www.acwing.com/problem/content/description/3474/【题目描述】 如上图所示&#xff0c;由正整数 1&#xff0c;2&#xff0c;3…… 组成了一颗特殊二叉树。 我们已知这个二叉树的最后一个结点是 n。 现在的问题是&#xff0c;结点 m 所在的子树中一共包括…

MobileNeRF在Windows上的配置

MobileNeRF于2023年提出&#xff0c;源码地址&#xff1a;https://github.com/google-research/jax3d/tree/main/jax3d/projects/mobilenerf &#xff0c;论文为&#xff1a;《MobileNeRF: Exploiting the Polygon Rasterization Pipeline for Efficient Neural Field Renderin…

QT自定义工具条渐变背景颜色一例

使用样式定义&#xff1a; QWidget* toolbar new QWidget(this);toolbar->setObjectName("main_tool");toolbar->setStyleSheet("#main_tool{background: qlineargradient(x1:0 , y1:0 , x2:1 , y2:0,""stop:0 rgba(0,255,0, 0.2),"&q…

Nuxt3 components公共组件

1.目录结构 效果实现&#xff1a;写一个公共的right组件&#xff0c;在index和about页面同时引用它 2.index页面引入 index页面显示效果 about页面引用及效果

组件的自定义事件

src/components/School.vue <template><div class"school"><h2>学校名称&#xff1a;{{ name}}</h2><h2>学校地址&#xff1a;{{ address }}</h2><button click"sendSchoolName">把学校名给App</button>…

数据集成的强大联盟:Elasticsearch、Kibana、Logstash、MySQL

通常&#xff0c;很多关系数据项目都使用 MySQL。 它对于标准的 CRUD 操作是有益的&#xff0c;但有时我们需要做额外的过程。 当我们搜索某些内容时&#xff0c;我们会消耗资源或合并多个表。 有时&#xff0c;即使不是&#xff0c;可能仍然需要复杂的 SQL 查询。 也许这不是正…

如何查看OpenAI的AccessToken?

如何查看OpenAI的AccessToken&#xff1f; 记录一下如何查看 OpenAI的 AccessToken 文章目录 如何查看OpenAI的AccessToken&#xff1f;前提具体操作总结 前提 &#x1f4a7;首先&#xff0c;在获取AccessToken前&#xff0c;你需要达成 以下两个条件: 拥有一个可用的OpenA…

ARM CORETEX M0简介

ARM CORETEX M0简介 1. M0处理器简单框图 处理器内核&#xff1a;逻辑控制与运算 内部总线系统&#xff1a;单总线将处理器与外部的存储器和外部连接&#xff0c;进行数据交互&#xff08;冯诺依曼架构&#xff0c;数据与指令一起&#xff09; NVIC&#xff1a;嵌套向量中断控…